Service worker not getting body from request - javascript

So I have a service worker for fetch:
self.addEventListener('fetch', (event) => {
const requestProcessor = (idToken) => {
let req = event.request;
// For same origin https requests, append idToken to header.
if ((self.location.protocol === 'https:' ||
self.location.hostname === 'localhost') &&
idToken) {
// Clone headers as request headers are immutable.
const headers = new Headers();
for (let entry of req.headers.entries()) {
headers.append(entry[0], entry[1]);
}
// Add ID token to header.
headers.append('Authorization', self.location.origin === getOriginFromUrl(event.request.url) ? `Bearer ${idToken}` : idToken);
try {
req = new Request(req.url, {
method: req.method,
headers: headers,
mode: self.location.origin === getOriginFromUrl(event.request.url) ? 'same-origin' : req.mode,
credentials: req.credentials,
cache: req.cache,
redirect: req.redirect,
referrer: req.referrer,
body: req.body,
bodyUsed: req.bodyUsed,
context: req.context
});
} catch (e) {
console.error(e);
}
}
return fetch(req);
};
event.respondWith(getIdToken().then(requestProcessor));
});
It is being called in another file like so:
export const makePostRequest = (url = '', params = {}) => {
return fetch(url, {
method: 'POST',
body: JSON.stringify(params),
headers: {
'Content-type': 'application/json'
}
}).then((res) => res).catch((err) => console.log(err));
};
For some reason, the req.body is always undefined inside of the service worker. Furthermore, it looks like the fetch request happens twice. When I put a breakpoint and step through the code, I can see that nothing from the fetch is being picked up by the service worker. I don't understand.

Okay, so this isn't obvious. So after some research this solved my issue:
self.addEventListener('fetch', (event) => {
if (getOriginFromUrl(event.request.url) === 'https://app.example.com') {
const requestProcessor = (idToken) => {
let newRequest = null;
// For same origin https requests, append idToken to header.
if ((self.location.protocol === 'https:' || self.location.hostname === 'localhost') && idToken) {
try {
newRequest = new Request(event.request, {
headers: new Headers({
...event.request.Headers,
'Content-Type': 'application/json',
Authorization: 'Bearer ' + idToken,
})
})
} catch (e) {
console.log(e);
}
}
return fetch(newRequest);
};
/* Fetch the resource after checking for the ID token.
This can also be integrated with existing logic to serve cached files
in offline mode.*/
event.respondWith(getIdToken().then(requestProcessor, requestProcessor));
}
});
I also had to set the mode:
export const makePostRequest = (url = '', params = {}) => {
return fetch(url, {
method: 'POST',
mode: 'cors',
headers: {
'Content-type': 'application/json'
},
body: JSON.stringify(params)
}).then((res) => res).catch((err) => console.log(err));
};
There were two issues:
By default the header's mode was set to no-cors. According to a previous SO answer, I had to set the mode to cors to allow for non-basic headers which would also include body.
The other issue had to do with the headers being immutable. This had to be changed to copy properly.

The Request object will implement methods like .blob().
await req.blob()

Related

HTTP function times out when subscribing an FCM token to a topic in Cloud Function

Minimum reproducible code:
index.ts:
import * as admin from "firebase-admin"
import fetch, { Headers } from "node-fetch";
interface BarPayload {
topic: string,
token: string,
}
exports.bar = functions.https.onCall(async (data, context) => {
if (data != null) {
const payload: BarPayload = {
topic: data.topic,
token: data.token,
}
const url = `https://${location}-${project}.cloudfunctions.net/subscribeToTopic`
await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
topic: payload.topic,
token: payload.token,
}),
})
}
return null;
});
export const subscribeToTopic = functions.https.onRequest(async (req, res) => {
const payload = req.body as BarPayload;
fetch('https://iid.googleapis.com/iid/v1/' + payload.token + '/rel/topics/' + payload.topic, {
method: 'POST',
headers: new Headers({
'Authorization': 'key=AA...Wp9',
'Content-Type': 'application/json'
})
}).then(response => {
if (response.status < 200 || response.status >= 400) {
res.sendStatus(299)
}
}).catch(error => {
console.error(error);
res.sendStatus(299)
})
return Promise.resolve();
})
I'm running bar in Flutter and I see the timeout error in Logs Explorer:
textPayload: "Function execution took 60051 ms. Finished with status: timeout"
But if I change my subscribeToTopic from HTTP function to a callable function, then it works fine. For example:
exports.subscribeToTopic = functions.https.onCall(async (data, context) => {
fetch('https://iid.googleapis.com/iid/v1/' + data.token + '/rel/topics/' + data.topic, {
method: 'POST',
headers: new Headers({
'Authorization': 'key=AA...Wp9',
'Content-Type': 'application/json'
})
}).then(response => {
if (response.status < 200 || response.status >= 400) {
console.log('Error = ' + response.error);
}
}).catch(error => {
console.error(error);
})
return null;
});
(I know I'm making some trivial mistake, and I'm new to Typescript. Any help would be appreciated :)
You should not do return Promise.resolve(); in the HTTPS Cloud Function:
HTTPS Cloud Functions shall be terminated with with send(), redirect() or end();
return Promise.resolve(); is executed before the asynchronous call to fetch is complete.
The following should do the trick (untested):
export const subscribeToTopic = functions.https.onRequest(async (req, res) => {
try {
const payload = req.body as BarPayload;
const response = await fetch('https://iid.googleapis.com/iid/v1/' + payload.token + '/rel/topics/' + payload.topic, {
method: 'POST',
headers: new Headers({
'Authorization': 'key=AA...Wp9',
'Content-Type': 'application/json'
})
});
if(response.status < 200 || response.status >= 400) {
res.status(299).send();
}
} catch (error) {
res.status(400).send();
}
})
However I don't understand why you separate your business logic in two Cloud Functions. Why don't you directly fetch https://iid.googleapis.com within the bar Callable Cloud Function?

Post action API with object parameter within the URL

I've got an API where some of the parameters need to be given within the URL.
Example of how my api url looks like: https://www.server.com/api/actions/execute?auth_type=apikey&data={"Name": "name","Email" : "email"}
What my code looks like right now
register = async () => {
let data = {"Name":this.state.name, "Email":this.state.email}
data = JSON.stringify(data)
let URL = 'https://www.server.com/api/actions/execute?auth_type=apikey&data=';
fetch(URL, {
method: 'POST',
headers: new Headers({
'Content-Type': 'application/json'
}),
body: data
})
.then((response) => response.text())
.then((responseText) => {
alert(responseText);
})
.catch((error) => {
console.error(error);
});
}
The response I get on my device:
{"code":"succes","details":{"userMessage":["java.lang.Object#2e56000c"],"output_type":void","id:"20620000000018001"},"message":"function executed succesfully"}
This is alle working fine when I test it in postman but I can't get it to work within React-Native. I've tried stuff like 'Content-Type':'application/x-www-form-urlencoded' already.
First install the package axios from the url https://www.npmjs.com/package/react-native-axios
Then create two service for handling get and post request so that you can reuse them
GetService.js
import axios from 'axios';
let constant = {
baseurl:'https://www.sampleurl.com/'
};
let config = {
headers: {
'Content-Type': 'multipart/form-data',
'Accept': 'application/json'
}
};
export const GetService = (data,Path,jwtKey) => {
if(jwtKey != ''){
axios.defaults.headers.common['Authorization'] = 'Bearer '+jwtKey;
}
try{
return axios.get(
constant.baseUrl+'api/'+Path,
data,
config
);
}catch(error){
console.warn(error);
}
}
PostService.js
import axios from 'axios';
let constant = {
baseurl:'https://www.sampleurl.com/'
};
let config = {
headers: {
'Content-Type': 'multipart/form-data',
'Accept': 'application/json'
}
};
export const PostService = (data,Path,jwtKey) => {
if(jwtKey != ''){
axios.defaults.headers.common['Authorization'] = 'Bearer '+jwtKey;
}
try{
return axios.post(
constant.baseUrl+'api/'+Path,
data,
config
);
}catch(error){
console.warn(error);
}
}
Sample code for using get and post services is given below
import { PostService } from './PostService';
import { GetService } from './GetService';
let uploadData = new FormData();
uploadData.append('key1', this.state.value1);
uploadData.append('key2', this.state.value2);
//uploadData.append('uploads', { type: data.mime, uri: data.path, name: "samples" });
let jwtKey = ''; // Authentication key can be added here
PostService(uploadData, 'postUser.php', jwtKey).then((resp) => {
this.setState({ uploading: false });
// resp.data will contain json data from server
}).catch(err => {
// handle error here
});
GetService({}, 'getUser.php?uid='+uid, jwtKey).then((resp) => {
// resp.data will contain json data from server
}).catch(err => {
// handle error here
});
If you need to pass parameters via URL you should use GET, if you use POST then the parameters should be passed in the body

HTTP headers not getting sent with fetch()

I'm trying to configure the backend API on my app and here's the code to send a request:
static async xhr(endpoint, args, method) {
const url = `${API_SERVER}${endpoint}`;
let formBody = [];
for (let property in args) {
let encodedKey = encodeURIComponent(property);
let encodedValue = encodeURIComponent(args[property]);
formBody.push(encodedKey + "=" + encodedValue);
}
formBody = formBody.join("&");
let options = Object.assign({ method: method }, args ? { body: formBody } : null );
try {
let headers = {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
};
accessToken = 'bdi8HD8js91jdoach7234h';
if(accessToken != null)
headers['Authorization'] = accessToken;
options.headers = headers;
return fetch(url, options).then( resp => {
console.log(resp);
let json = resp.json();
if(resp.status >= 200 && resp.status < 300) {
if (resp.ok) {
return json
}
} else {
return {};
}
return json.then(err => {throw err});
});
} catch (error) {
return null;
}
}
Note: I debugged and found that the headers are correctly getting added to the options variable, but for some reason, the server isn't receiving the Authorization header.
I used Postman to send the exact same request with the exact same headers and I'm getting the correct response via it. I have no idea what's wrong, except it would only be so if the headers aren't getting sent in the first place.
Can someone please tell me what am I doing wrong? Thanks!
The headers option has to be an instance of Headers. You can transform your current headers object to a Headers instance by passing it to its constructor like this:
const headers = new Headers({
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
});
Note that I also replaced let with const since that variable is not going to be reassigned.
To change a header or add a new header to that Headers instance, you can use the set method. Instead of headers['Authorization'] = accessToken you'd do ...
headers.set('Authorization', accessToken)

Axios not passing headers on requests

I'm building a VueJS application and I'm using JSON web tokens as my auth system. When I log the user, I store the token with localStorage and works fine. I check the headers and it's in the 'Authorization' param.
I pass with axios.defaults.headers.common['Authorization'] = localStorage.getItem('token')
I see the headers and it's okay. But when I execute a get request to an protected route in my API, return 'unauthorized'. But when I pass the header with token manually in the request, works fine.
Somebody know how to pass the header automatically when executing some request?
try this..
//in get request
const auth = {
headers: {Authorization:'JWT ' + localStorage.getItem('token')}
}
axios.get('http://yourapi.com',auth).then(result => {
console.log(result.data)
})
//in post request
const auth = {
headers: {Authorization:'JWT ' + localStorage.getItem('token')}
}
//note:auth will be 3rd parameter in post request
axios.post('http://yourapi.com',{somekey:'some value'},auth).then(result => {
console.log(result.data)
})
You can use axios.create to create a new axios instance with a config object, including the headers. The configuration will be used for each subsequent calls you make using that instance.
Something like this worked for me:
var App = Vue.component('app', {
mounted () {
this.response = null
this.axiosInstance = axios.create({
baseURL: 'http://localhost:5000/',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
}
})
},
data () {
return {
response: this.response,
}
},
methods: {
login () {
this.axiosInstance.post('login', {username: 'test', password: 'test'})
.then(resp => {
this.accessToken = resp.data.access_token
this.axiosInstance.defaults.headers['Authorization'] = 'Bearer ' + this.accessToken
})
.catch(err => this.response = err.response.status + ' ' + err.response.statusText)
},
protected () {
this.axiosInstance.get('protected')
.then(resp => this.response = resp.data)
.catch(err => this.response = err.response.status + ' ' + err.response.statusText)
}
},
template: '<div><button #click="login">Connect</button><button #click="protected">Protected</button></div>'
})
interceptor which includes your auth token in every request as an Authorization header:
axios.interceptors.request.use(
function(config) {
const token = localStorage.getItem('token')
if (token) config.headers.Authorization = `Bearer ${token}`
return config
},
function(error) {
return Promise.reject(error)
}
)
you could place it in the main file, for example main.js
Check whether server get token from header of "Authorization"
axios.defaults.headers.common['Authorization'] = 'Bearer ' + localStorage.getItem('token')
if No. 2 works, then you may want to execute apis even if web is refreshed, then follow:
axios.interceptors.request.use(function (config) {
const token = 'Bearer ' + localStorage.getItem('token');
config.headers.Authorization = `Bearer ${token}`;
return config;
});
For me issue was with capital Headers vs headers.
Should be lower case. My IDE got me the wrong autocomplete (i.e. with capital H)
This works:
await axios.get(url, {
headers: { 'x-custom-header': 'super header value' }
});
This doesn't!
await axios.get(url, {
Headers: { 'x-custom-header': 'super header value' }
});

Fetch: POST JSON data

I'm trying to POST a JSON object using fetch.
From what I can understand, I need to attach a stringified object to the body of the request, e.g.:
fetch("/echo/json/",
{
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
method: "POST",
body: JSON.stringify({a: 1, b: 2})
})
.then(function(res){ console.log(res) })
.catch(function(res){ console.log(res) })
When using jsfiddle's JSON echo I'd expect to see the object I've sent ({a: 1, b: 2}) back, but this does not happen - chrome devtools doesn't even show the JSON as part of the request, which means that it's not being sent.
With ES2017 async/await support, this is how to POST a JSON payload:
(async () => {
const rawResponse = await fetch('https://httpbin.org/post', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({a: 1, b: 'Textual content'})
});
const content = await rawResponse.json();
console.log(content);
})();
Can't use ES2017? See #vp_art's answer using promises
The question however is asking for an issue caused by a long since fixed chrome bug.
Original answer follows.
chrome devtools doesn't even show the JSON as part of the request
This is the real issue here, and it's a bug with chrome devtools, fixed in Chrome 46.
That code works fine - it is POSTing the JSON correctly, it just cannot be seen.
I'd expect to see the object I've sent back
that's not working because that is not the correct format for JSfiddle's echo.
The correct code is:
var payload = {
a: 1,
b: 2
};
var data = new FormData();
data.append( "json", JSON.stringify( payload ) );
fetch("/echo/json/",
{
method: "POST",
body: data
})
.then(function(res){ return res.json(); })
.then(function(data){ alert( JSON.stringify( data ) ) })
For endpoints accepting JSON payloads, the original code is correct
I think your issue is jsfiddle can process form-urlencoded request only. But correct way to make json request is pass correct json as a body:
fetch('https://httpbin.org/post', {
method: 'POST',
headers: {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json'
},
body: JSON.stringify({a: 7, str: 'Some string: &=&'})
}).then(res => res.json())
.then(res => console.log(res));
From search engines, I ended up on this topic for non-json posting data with fetch, so thought I would add this.
For non-json you don't have to use form data. You can simply set the Content-Type header to application/x-www-form-urlencoded and use a string:
fetch('url here', {
method: 'POST',
headers: {'Content-Type':'application/x-www-form-urlencoded'}, // this line is important, if this content-type is not set it wont work
body: 'foo=bar&blah=1'
});
An alternative way to build that body string, rather then typing it out as I did above, is to use libraries. For instance the stringify function from query-string or qs packages. So using this it would look like:
import queryString from 'query-string'; // import the queryString class
fetch('url here', {
method: 'POST',
headers: {'Content-Type':'application/x-www-form-urlencoded'}, // this line is important, if this content-type is not set it wont work
body: queryString.stringify({for:'bar', blah:1}) //use the stringify object of the queryString class
});
After spending some times, reverse engineering jsFiddle, trying to generate payload - there is an effect.
Please take eye (care) on line return response.json(); where response is not a response - it is promise.
var json = {
json: JSON.stringify({
a: 1,
b: 2
}),
delay: 3
};
fetch('/echo/json/', {
method: 'post',
headers: {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json'
},
body: 'json=' + encodeURIComponent(JSON.stringify(json.json)) + '&delay=' + json.delay
})
.then(function (response) {
return response.json();
})
.then(function (result) {
alert(result);
})
.catch (function (error) {
console.log('Request failed', error);
});
jsFiddle: http://jsfiddle.net/egxt6cpz/46/ && Firefox > 39 && Chrome > 42
2021 answer: just in case you land here looking for how to make GET and POST Fetch api requests using async/await or promises as compared to axios.
I'm using jsonplaceholder fake API to demonstrate:
Fetch api GET request using async/await:
const asyncGetCall = async () => {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
const data = await response.json();
// enter you logic when the fetch is successful
console.log(data);
} catch(error) {
// enter your logic for when there is an error (ex. error toast)
console.log(error)
}
}
asyncGetCall()
Fetch api POST request using async/await:
const asyncPostCall = async () => {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
// your expected POST request payload goes here
title: "My post title",
body: "My post content."
})
});
const data = await response.json();
// enter you logic when the fetch is successful
console.log(data);
} catch(error) {
// enter your logic for when there is an error (ex. error toast)
console.log(error)
}
}
asyncPostCall()
GET request using Promises:
fetch('https://jsonplaceholder.typicode.com/posts')
.then(res => res.json())
.then(data => {
// enter you logic when the fetch is successful
console.log(data)
})
.catch(error => {
// enter your logic for when there is an error (ex. error toast)
console.log(error)
})
POST request using Promises:
fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
// your expected POST request payload goes here
title: "My post title",
body: "My post content."
})
})
.then(res => res.json())
.then(data => {
// enter you logic when the fetch is successful
console.log(data)
})
.catch(error => {
// enter your logic for when there is an error (ex. error toast)
console.log(error)
})
GET request using Axios:
const axiosGetCall = async () => {
try {
const { data } = await axios.get('https://jsonplaceholder.typicode.com/posts')
// enter you logic when the fetch is successful
console.log(`data: `, data)
} catch (error) {
// enter your logic for when there is an error (ex. error toast)
console.log(`error: `, error)
}
}
axiosGetCall()
POST request using Axios:
const axiosPostCall = async () => {
try {
const { data } = await axios.post('https://jsonplaceholder.typicode.com/posts', {
// your expected POST request payload goes here
title: "My post title",
body: "My post content."
})
// enter you logic when the fetch is successful
console.log(`data: `, data)
} catch (error) {
// enter your logic for when there is an error (ex. error toast)
console.log(`error: `, error)
}
}
axiosPostCall()
I have created a thin wrapper around fetch() with many improvements if you are using a purely json REST API:
// Small library to improve on fetch() usage
const api = function(method, url, data, headers = {}){
return fetch(url, {
method: method.toUpperCase(),
body: JSON.stringify(data), // send it as stringified json
credentials: api.credentials, // to keep the session on the request
headers: Object.assign({}, api.headers, headers) // extend the headers
}).then(res => res.ok ? res.json() : Promise.reject(res));
};
// Defaults that can be globally overwritten
api.credentials = 'include';
api.headers = {
'csrf-token': window.csrf || '', // only if globally set, otherwise ignored
'Accept': 'application/json', // receive json
'Content-Type': 'application/json' // send json
};
// Convenient methods
['get', 'post', 'put', 'delete'].forEach(method => {
api[method] = api.bind(null, method);
});
To use it you have the variable api and 4 methods:
api.get('/todo').then(all => { /* ... */ });
And within an async function:
const all = await api.get('/todo');
// ...
Example with jQuery:
$('.like').on('click', async e => {
const id = 123; // Get it however it is better suited
await api.put(`/like/${id}`, { like: true });
// Whatever:
$(e.target).addClass('active dislike').removeClass('like');
});
Had the same issue - no body was sent from a client to a server.
Adding Content-Type header solved it for me:
var headers = new Headers();
headers.append('Accept', 'application/json'); // This one is enough for GET requests
headers.append('Content-Type', 'application/json'); // This one sends body
return fetch('/some/endpoint', {
method: 'POST',
mode: 'same-origin',
credentials: 'include',
redirect: 'follow',
headers: headers,
body: JSON.stringify({
name: 'John',
surname: 'Doe'
}),
}).then(resp => {
...
}).catch(err => {
...
})
This is related to Content-Type. As you might have noticed from other discussions and answers to this question some people were able to solve it by setting Content-Type: 'application/json'. Unfortunately in my case it didn't work, my POST request was still empty on the server side.
However, if you try with jQuery's $.post() and it's working, the reason is probably because of jQuery using Content-Type: 'x-www-form-urlencoded' instead of application/json.
data = Object.keys(data).map(key => encodeURIComponent(key) + '=' + encodeURIComponent(data[key])).join('&')
fetch('/api/', {
method: 'post',
credentials: "include",
body: data,
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
The top answer doesn't work for PHP7, because it has wrong encoding, but I could figure the right encoding out with the other answers. This code also sends authentication cookies, which you probably want when dealing with e.g. PHP forums:
julia = function(juliacode) {
fetch('julia.php', {
method: "POST",
credentials: "include", // send cookies
headers: {
'Accept': 'application/json, text/plain, */*',
//'Content-Type': 'application/json'
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8" // otherwise $_POST is empty
},
body: "juliacode=" + encodeURIComponent(juliacode)
})
.then(function(response) {
return response.json(); // .text();
})
.then(function(myJson) {
console.log(myJson);
});
}
It might be useful to somebody:
I was having the issue that formdata was not being sent for my request
In my case it was a combination of following headers that were also causing the issue and the wrong Content-Type.
So I was sending these two headers with the request and it wasn't sending the formdata when I removed the headers that worked.
"X-Prototype-Version" : "1.6.1",
"X-Requested-With" : "XMLHttpRequest"
Also as other answers suggest that the Content-Type header needs to be correct.
For my request the correct Content-Type header was:
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
So bottom line if your formdata is not being attached to the Request then it could potentially be your headers. Try bringing your headers to a minimum and then try adding them one by one to see if your problem is resolved.
If your JSON payload contains arrays and nested objects, I would use URLSearchParams and jQuery's param() method.
fetch('/somewhere', {
method: 'POST',
body: new URLSearchParams($.param(payload))
})
To your server, this will look like a standard HTML <form> being POSTed.
You could do it even better with await/async.
The parameters of http request:
const _url = 'https://jsonplaceholder.typicode.com/posts';
let _body = JSON.stringify({
title: 'foo',
body: 'bar',
userId: 1,
});
const _headers = {
'Content-type': 'application/json; charset=UTF-8',
};
const _options = { method: 'POST', headers: _headers, body: _body };
With clean async/await syntax:
const response = await fetch(_url, _options);
if (response.status >= 200 && response.status <= 204) {
let data = await response.json();
console.log(data);
} else {
console.log(`something wrong, the server code: ${response.status}`);
}
With old fashion fetch().then().then():
fetch(_url, _options)
.then((res) => res.json())
.then((json) => console.log(json));
**//POST a request**
const createTodo = async (todo) => {
let options = {
method: "POST",
headers: {
"Content-Type":"application/json",
},
body: JSON.stringify(todo)
}
let p = await fetch("https://jsonplaceholder.typicode.com/posts", options);
let response = await p.json();
return response;
}
**//GET request**
const getTodo = async (id) => {
let response = await fetch('https://jsonplaceholder.typicode.com/posts/' + id);
let r = await response.json();
return r;
}
const mainFunc = async () => {
let todo = {
title: "milan7",
body: "dai7",
userID: 101
}
let todor = await createTodo(todo);
console.log(todor);
console.log(await getTodo(5));
}
mainFunc()
I think that, we don't need parse the JSON object into a string, if the remote server accepts json into they request, just run:
const request = await fetch ('/echo/json', {
headers: {
'Content-type': 'application/json'
},
method: 'POST',
body: { a: 1, b: 2 }
});
Such as the curl request
curl -v -X POST -H 'Content-Type: application/json' -d '#data.json' '/echo/json'
In case to the remote serve not accept a json file as the body, just send a dataForm:
const data = new FormData ();
data.append ('a', 1);
data.append ('b', 2);
const request = await fetch ('/echo/form', {
headers: {
'Content-type': 'application/x-www-form-urlencoded'
},
method: 'POST',
body: data
});
Such as the curl request
curl -v -X POST -H 'Content-type: application/x-www-form-urlencoded' -d '#data.txt' '/echo/form'
You only need to check if response is ok coz the call not returning anything.
var json = {
json: JSON.stringify({
a: 1,
b: 2
}),
delay: 3
};
fetch('/echo/json/', {
method: 'post',
headers: {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json'
},
body: 'json=' + encodeURIComponent(JSON.stringify(json.json)) + '&delay=' + json.delay
})
.then((response) => {if(response.ok){alert("the call works ok")}})
.catch (function (error) {
console.log('Request failed', error);
});
// extend FormData for direct use of js objects
Object.defineProperties(FormData.prototype, {
load: {
value: function (d) {
for (var v in d) {
this.append(v, typeof d[v] === 'string' ? d[v] : JSON.stringify(d[v]));
}
}
}
})
var F = new FormData;
F.load({A:1,B:2});
fetch('url_target?C=3&D=blabla', {
method: "POST",
body: F
}).then( response_handler )
you can use fill-fetch, which is an extension of fetch. Simply, you can post data as below:
import { fill } from 'fill-fetch';
const fetcher = fill();
fetcher.config.timeout = 3000;
fetcher.config.maxConcurrence = 10;
fetcher.config.baseURL = 'http://www.github.com';
const res = await fetcher.post('/', { a: 1 }, {
headers: {
'bearer': '1234'
}
});

Categories

Resources