Render HTML + Javascript from HTTP response - javascript

I am sending a HTTP GET request from a browser to an external API using React. I'm getting a response containing some HTML and Javascript which I would like to render in my browser.
Here's my code so far:
const url = getExternalEndpoint()
fetch(url)
.then(function(response) {
return response.text();
}).then(function(data) {
console.log(data);
})
Based on Retrieve data from a ReadableStream object?
So I can see the HTML in the console, but I'm not sure how to render it.
For context, the external server I'm sending the request to is an OpenID Connect server.

So, there is one library called react-html-parser
To install, use the following command
npm install react-html-parser
# or 
yarn add react-html-parser
Here, you can use the state to update the value from API.
import ReactHtmlParser from 'react-html-parser';
const [html_string, Sethtml_string] = useState('')
//set value in the html_string
<div> { ReactHtmlParser (html_string) } </div>

Related

sveltekit fetch function with ajax requests

In my sveltekit app I make AJAX calls to my api endpoints. For example:
+page.svelte
<script>
async function get_card() {
const url = '/api/card/?category=' + $page.params.slug;
const response = await fetch(url, {
method: 'GET',
})
const card = await response.json();
return card;
}
</script>
In the browser javascript console I get this warning:
Loading /api/card/?category=Neurology using `window.fetch`.
For best results, use the `fetch` that is passed to your `load`
function: https://kit.svelte.dev/docs/load#making-fetch-requests
But as far as I can tell, that fetch function is only accessible to me on the server, and I do not see a way to use it in a script that may run on the client (such as +page.svelte). I tried passing the function as part of the data object from load:
+layout.server.js
export const load = async ({ fetch, locals }) => {
return {
email: locals.user.email,
group: locals.user.group,
fetch: fetch
}
}
But, not surprisingly, that does not work since the function is not serializable.
Am I Doing It Wrong™, or should I just ignore the warning?
fetch is originally a browser API and SvelteKit defines it on the server as well, if it does not exist. The warning is there to tell you that you are creating another round trip to the server (one for the page and one for the data) when you possibly could have loaded the data on the server so it could be transmitted as part of the page (during server-side rendering).
If the code of your function is not executed right away, then this is a false positive (recent issue on this). I.e. if the data should be requested at a significantly later point, there is no way to bundle the request with the page.
(You are definitely not meant to pass on the fetch of load, you are supposed to use it to get the data.)

Data posted to flask endpoint from JS not processed in endpoint

I have written a simple todo app with react acting as a frontend and flask handling CRUD from a DB. The app is using axios to handle the requests; GET completes fine however when attempting to POST JSON the flask api returns a 400 error. Here's some condensed sample code.
JS POST function.
function testPost(){
axios.post('http://'+window.location.hostname+':8000/todo/', {
title: "test123",
}).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
}
Serverside
class Todo(Resource):
def post(self): # create a new todo
conn = pool.getconn()
cur = conn.cursor()
app.logger.info(request.form['title'])
cur.execute("INSERT INTO todo (task, done) VALUES (%s, %s)", (request.form['title'], False))
conn.commit()
app.logger.error(e)
cur.close()
pool.putconn(conn)
Other methods not shown
Then the rest of the server code attaching the resource to the api and the CORS setup (not shown in file order)
app = Flask(__name__)
CORS(app, methods=['POST','GET','PUT','DELETE'])
api = Api(app)
api.add_resource(Todo, '/todo/')
app.run(debug = True, host='0.0.0.0', port=port)
Tests
Using python to test the api works fine, running this in a seperate python file will add to the DB.
response = requests.post(URL + "todo/", data={"title": f"test{randint(1, 100)}"})
My best guess is that axios is not adding the data to the request in a way that the backend is unable to process. Before using axios I tried to make the request with XMLHttprequest however this presented the same problem. I swapped to axios on the recommendation of someone else, given its alleged improved simplicity.
request.form['key'] and request.get_json()['key'] are completely different fields python requests in the way I used it posts to the former and js posts to the latter. Modifying the function to use whichever is available fixes this.

Use Next.js Dynamic routing query object in an SWR fetch request

When using Next.js dynamic routing I'm trying to make an SWR fetch request using the routing query object, but my SWR fetch request is being called before the query object is set.
Given the dynamic route /posts/[id], consider the page /posts/123.
import { useRouter } from 'next/router';
import useSWR from 'swr';
export default function MyPage() {
const router = useRouter();
const { id } = router.query;
const url = `https://my.api.com/posts/${id}` // I've also tried using let here
const { data, error } = useSWR(url, fetcher);
console.log(url)
This URL initially console logs as https://my.api.com/posts/undefined and an error is returned from the API because https://my.api.com/posts/undefined is, of course, not a valid path.
Immediately after, the URL console logs correctly as https://my.api.com/posts/123 and the data on the page usually then populates, but sometimes the data doesn't populate and it's stuck in a 'loading' state. When I hardcode the URL this never happens.
Is there something I'm doing wrong here? Why is the query object not available immediately? Is there a way to elegantly wait for it to be set?
You could try to use conditional data fetching like so:
const { data, error } = useSWR(id ? url : null, id ? fetcher : null);
Also check following conversation: https://github.com/vercel/next.js/discussions/15952

shorten axios text/html response

I am sending an Axios request to a web page for scraping a little string off of it, but the returned response is a large html, and I only need a little part of it, is there a way to somehow shorten the response so I can save data and make the request faster?
const longHtml = await axios.get('https://example.com');
const shortHtml = longHtml.data //get short data here
If I understand what your trying to do, you wan't to stop the request when you find the data you want, you could use htmlparser2 and feed it a stream from axios and then register listeners and when you get the element you need you can end the stream.
Web scraping is a technique used for retrieving data from websites. You fetch the page's contents, and after that extract the data you need from the page.
here an example by using axios and cheerio
const axios = require("axios")
const cheerio = require("cheerio")
async function fetchHTML(url) {
const { data } = await axios.get(url)
return cheerio.load(data)
}
const $ = await fetchHTML("https://example.com")
// Print the full HTML
console.log(`Site HTML: ${$.html()}\n\n`)
// Print some specific page content
console.log(`First h1 tag: ${$('h1').text()}`)

Parse raw body on cloudflare-worker service(Non NODE)

I've created an api server'ish environment on cloudflare using cloudflare-worker and there is no node server running(cloudflare-worker is pretty much serverless event handler service). It does provide the configurations to handle any subdomain calls much like how api works. I've used a package called cf-worker-router to do so.
My cloud service looks like this:
import { ApiError, ApiRedirect, DomainRouter, FetchRouter } from 'cf-worker-router';
const router = new FetchRouter();
// add the cloudflare event listener
addEventListener('fetch', (event) => {
router.onFetch(event);
});
router.route('/users', 'POST', async (event) => {
// automatically converts anything not of Response type to ApiResponse
return await event.request.text();
});
And what I did was create a POST request to the url and supplied some body to the request. I was able to get the request text successfully but now I can't figure out how to parse the text I received.
When using the request as multipart/form-data request and the received body text is as follows:
"----------------------------093590450792211419875705\r\nContent-Disposition: form-data; name=\"name\"\r\n\r\nJon Doe\r\n----------------------------093590450792211419875705--\r\n"
I tried sending application/x-www-form-urlencoded and I the response text as such:
"name=Jon%20Doe"
And Similar for application/json request:
"{\n\t\"name\": \"Jon Doe\"\n}"
Since cloudflare is not using nodejs server, body-parser can't be applied here. This service is pretty much an open api so it needs to take care of all sorts of request content types. Is there any way to identify and decode the strignified contents from any of these content types to a valid object in javascript?
To handle form data uploads, you can use the request.formData() method which will return a promise of a FormData object.
For example:
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
const formData = await request.formData();
const name = formData.get('name');
return new Response(`Hello ${name}`);
}

Categories

Resources