I am trying to send a fetch request to a URL to receive some JSON, all I get back is HTTP/1.1 200 OK, when I try to console.log my request, I don't see anything in the console, I am trying to console.log the request as JSON. I am using Cloudflare's wrangler tool for the project and coding it in javascript Here is my code:
addEventListener('fetch', event => {
event.respondWith(handleRequest((event)))
})
/**
* Respond with hello worker text
* #param {Request} request
*/
async function handleRequest(request) {
return new Response('Hello worker!', {
headers: { 'content-type': 'application/json' },
})
}
const url =`URL`;
const res="";
fetch(`MYURL`)
.then((response) => {
return response.json();
})
.then((data) => {
dataRecieved=JSON.parse(data);
console.log(dataRecieved);
});
'Hello worker!' is not a valid JSON so JSON.parse(data) will not be able to work properly. You should use a code like this to return a valid JSON in the response:
return new Response('{"variants":["your-private-url/variants/1","your-private-url/variants/2"]}', {
headers: { 'content-type': 'application/json' },
status: 200
})
Now to have the result as you mentioned in your comments you need to remove the event listener and handle the fetch call this way:
fetch('your-private-url')
.then((response) => {
return response.json();
})
.then((data) => {
// 'data' here contains the object returned by your request.
// So you can log the whole object received to see its content:
console.log('Received data:\n', data);
// And you can access the fields and log them:
data.variants.forEach(variant => {
console.log('Reveived variant: ', variant);
});
});
Related
So I moved over a non-reusable fetch request code snippet to my API:
let response = await fetch(visitURL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + userJWT
},
body: JSON.stringify(endingVisit)
});
if (response.ok) {
let {visitId, createdAt} = await response.json();
const viewVisitDto = new ViewVisitDto(`${visitId}${createdAt}${visitorId}${doctorId}${oldPatientId}`);
return viewVisitDto;
} else {
throw new Error("deactivated!")
}
I was able to get this far:
axios.post(visitURL, {
headers,
body: JSON.stringify(visit)
}).then((response) => {
console.log(response);
}).catch((error) => {
console.log(error);
})
But does not exactly give me the visitId and createdAt from the response and I cannot use a response.ok nor a response.json(). Essentially I need to pull out that visitId and createdAt that should be coming back in the response.
I also tried just using node-fetch library, but although in VS code it seems to accept it, TypeScript is not happy with it even when I do install #types/node-fetch and even when I create a type definition file for it, my API just doesn't like it.
Guessing what you are after is
// don't know axios, but if it returns a promise await it
const dto = await axios.post(visitURL, {
headers,
body: JSON.stringify(visit)
}).then((response) => {
// parse response
return {resonse.visitId, resonse.createdAt}
}).then(({visitId, createdAt}) => {
// form dto (where are other vals)?
return new ViewVisitDto(`${visitId}${createdAt}${visitorId}${doctorId}${oldPatientId}`);
}).catch((error) => {
console.log(error);
})
However - you don't mention where doctorId and oldPatientId come from... You try providing more info, including output of the console.log's and the surrounding code
I am trying to make an API call from my JavaScript app to an endpoint in another application.
When I call the endpoint I get the status code and the message, but I cannot access the response body in any way. I have tried different ways to get the data, but nothing seems to work for me.
In the method "someAction", I want to use the data in the response/result from the API call. I added the outputs that the single log-lines print in the code.
How can "result" be undefined while "result.status/message" are defined?
What do I have to do in order to get the data/body as JSON or String?
The API itself is tested and returns data when tested in postman.
Thanks for your help!
const request = require('request')
let callEndpoint = () => {
return new Promise((resolve, reject) => {
const url = `https://my.api.com/endpoint`
const requestOptions = {
url: url,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
'My-API-Authorization': '123456789'
},
json: true,
strictSSL: false
}
request.get(requestOptions, (err, response) => {
if(err)
{
return reject(err);
}
return resolve(response);
});
});
}
let someAction = () => {
callEndpoint()
.then(result => {
logger.logInfo(result.statusCode) // => 200
logger.logInfo(result.statusMessage) // => OK
logger.logInfo(result) // => undefined
logger.logInfo(result.toString()) // => [object Object]
logger.logInfo(result.body) // => undefined
logger.logInfo(result.data) // => undefined
JSON.parse(result.toString()) // => Unexpected token o in JSON at position 1
JSON.parse(result) // => Unexpected token o in JSON at position 1
// DO SOME STUFF WITH THE RESULT
})
}
I want to use a Javascript serviceworker to log outgoing requests. My current approach is this:
self.addEventListener('fetch', function(event) {
var req = new Request("https://example.com?url=" + encodeURI(event.request.url), {
method: event.request.method,
headers: event.request.headers,
body: event.request.body
});
fetch(req);
});
This works fine for GET requests, but it doesn't work for the body of POST/PUT requests. I tried using body: event.request.body.blob(), but that did not work either.
Is there a simple way to access the body of a fetched request in serviceworkers and resend it elsewhere?
You could do something like the following:
self.addEventListener("fetch", (event) => {
const requestClone = event.request.clone();
event.respondWith(
(async function () {
const params = await requestClone.json().catch((err) => err);
if (params instanceof Error) {
// this is a simple check, but handle errors appropriately
}
if (event.request.method === "POST") {
console.log(`POST request with params: ${params}`);
// do work here
}
return fetch(event.request);
})()
);
});
Note that you have to create a clone for the event.request to be able to call the text method on it because the request is a stream and can only be consumed once, so you'd run into issues if you tried to grab the request's params and then use it for something else.
Also, you could use any of the following methods to retrieve the body from a request, so use whatever is appropriate:
event.request.arrayBuffer()
event.request.blob()
event.request.json()
event.request.text()
event.request.formData()
Assuming the above code snippet is included in your ServiceWorker file, the following example would give you what you need:
fetch("https://jsonplaceholder.typicode.com/posts", {
method: "POST",
body: JSON.stringify({ title: "foo", body: "bar", userId: 1 }),
headers: { "Content-Type": `application/json` },
})
.then((response) => response.json())
.then((json) => console.log(`fetch response`, json))
.catch((error) => console.error(`fetch error`, error));
// console logs
// >> POST request with {"title":"foo","body":"bar","userId":1} (worker.js)
// >> fetch response {title: "foo", body: "bar", userId: 1, id: 101} (index.js)
I am trying to load a data from my firebase backend but getting this error
Uncaught (in promise) TypeError: response.json is not a function
my code is as below :
import axios from 'axios';
export const loadData = ({ commit }) => {
console.log('getting data from server...');
axios
.get('data.json')
.then(response => response.json())
.then(data => {
if (data) {
const stocks = data.stocks;
const stockPortfolio = data.stockPortfolio;
const funds = data.funds;
const portfolio = {
stockPortfolio,
funds
};
commit('SET_STOCKS', stocks);
commit('SET_PORTFOLIO', portfolio);
console.log('Commit done ');
}
});
};
however, if I try response.data instead of response.json it works and successfully loads the data, so I am curious what the difference is and why the first one doesn't work.
Because of the axios package, it has a specific response schema https://github.com/axios/axios#response-schema
The response for a request contains the following information.
{
// `data` is the response that was provided by the server
data: {},
// `status` is the HTTP status code from the server response
status: 200,
// `statusText` is the HTTP status message from the server response
statusText: 'OK',
// `headers` the headers that the server responded with
// All header names are lower cased
headers: {},
// `config` is the config that was provided to `axios` for the request
config: {},
// `request` is the request that generated this response
// It is the last ClientRequest instance in node.js (in redirects)
// and an XMLHttpRequest instance in the browser
request: {}
}
With axios you don't need an extra .json() .Responses are already served as javascript object, no need to parse, simply get response and access data. You could use directly something like
axios.get('/user/12345')
.then(function (response) {
console.log(response.data);
console.log(response.status);
console.log(response.statusText);
console.log(response.headers);
console.log(response.config);
});
You only need to use the Body.json() method if you are trying to resolve the promise from a Response stream. You may read more about it on the documentation. One use case of doing so would be when you are making a HTTP request using the fetch API, whereby you will have to call Body.json() to return the response body.
let response = await fetch(url);
if (response.ok) { // if HTTP-status is 200-299
// get the response body (the method explained below)
let json = await response.json();
} else {
alert("HTTP-Error: " + response.status);
}
For axios, you only need to resolve the promose after making a GET request
axios.get(url[, config])
and thus, the following code below works, as the returned response body is handled within the .then() block when you resolve the promise.
axios
.get('data.json')
.then(response => console.log(response.data))
const CollectData = async () => {
let result = await fetch('http://localhost:5400/Enquiry', {
method: "post",
body: JSON.stringify({ name, email, contact, message }),
headers: {
"Content-Type": "application/json",
}
});
result = await result.json();
console.log(result);
if (result) {
navigate("/");
}
I am sending a status code 422 from my backend code with response body which contains the description of the error. I am using axios post as below to post a request:
post: function(url, reqBody) {
const request = axios({
baseURL: config.apiUrl,
url: url,
headers: {
'Content-Type': 'application/json',
'Authorization': sessionStorage.getItem('token')
},
method: 'POST',
data: reqBody,
responseType: 'json'
});
return request
.then((res) => {
return res;
})
.catch((error) => {
console.log(error);
return error;
})
}
The problem is when backend is returning error code 422, the error object I am catching has no information about response body. Is there any way I can retrieve the error text?
I had this same issue and the answer (as per Axios >= 0.13) is to specifically check error.response.data:
axios({
...
}).then((response) => {
....
}).catch((error) => {
if( error.response ){
console.log(error.response.data); // => the response payload
}
});
See here for more details.
The "body" of an AXIOS error response depends from the type of response the request had.
If you would like full details about this issue you can see this blogpost: How to catch the body of an error in AXIOS.
In summary AXIOS will return 3 different body depending from the error:
Wrong request, we have actually done something wrong in our request (missing argument, bad format), that is has not actually been sent. When this happen, we can access the information using error.message.
axios.get('wrongSetup')
.then((response) => {})
.catch((error) => {
console.log(error.message);
})
Bad Network request: This happen when the server we are trying to reach does not respond at all. This can either be due to the server being down, or the URL being wrong.
In this case, we can access the information of the request using error.request.
axios.get('network error')
.then((response) => {})
.catch((error) => {
console.log(error.request );
});
Error status: This is the most common of the request. This can happen with any request that returns with a status that is different than 200. It can be unauthorised, not found, internal error and more. When this error happen, we are able to grasp the information of the request by accessing the parameter specified in the snippets below. For the data (as asked above) we need to access the error.response.data.
axios.get('errorStatus')
.then((response) => {})
.catch((error) => {
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
})
For those using await/async and Typescript
try {
const response = await axios.post(url, body)
} catch (error) {
console.log(error.response.data);
}
For react native it just worked for me
api.METHOD('endPonit', body)
.then(response => {
//...
})
.catch (error => {
const errorMessage = JSON.parse(error.request.response)
console.log(errorMessage.message)
})
We can check error.response.data as #JoeTidee said. But in cases response payload is blob type? You can get error response body with the below code.
axios({
...
}).then((response) => {
....
}).catch(async (error) => {
const response = error.response
if(typeof response.data.text === function){
console.log(await response.data.text()); // => the response payload
} else {
console.log(response.data)
}
});
I am returning a string from backend but expecting a json as response type. So I need to return an object instead of string for axios to process it properly.
In my case I wanted to retrieve a response 404 error message (body).
I got body with error.response.data but I couldn't display it because the type was ArrayBuffer.
Solution:
axios.get(url, { responseType: 'arraybuffer' }).then(
response => {...},
error => {
const decoder = new TextDecoder()
console.log(decoder.decode(error.response.data))
}
)
Related posts:
Converting between strings and ArrayBuffers