I'm trying to do a patch to modify some informations using a form.
I take the new data, if they are modify and then create a new FormData. Then I pass the id and the formdata to do a patch. But something in the patch goes wrong.
I have a page in which I take the previous information( I pass these informations using react-router-dom and have a form to modify the data.
FormPage.js
When the submit button is press I call this:
class MeetingModify extends Components{
//the state taken from the previous page
handleSubmit(event){
event.preventDefault();
const idmeet = this.state.meet.id
var newMeet = new FormData();
if(this.state.information != this.props.location.state.information){
newMeet.append("information", this.state.information);
}
if(this.state.date != this.props.location.state.date){
newMeet.append("date", this.state.date);
}
if(this.state.hours != this.props.location.state.hours){
newMeet.append("hours", this.state.hours);
}
this.props.changeMeeting(idmeet, newMeet);
}
render(){
return(
//..form..
)
function mapDispatchToProps(dispatch) {
return {
changeMeeting: (idmeet, newMeet) => dispatch(changeMeeting(idmeeting, newMeet)),
};
}
export default connect(null, mapDispatchToProps)(MeetingModify);
in the Actions.js
export const changeMeeting = (idmeet, newMeet) => {
return (dispatch) => {
fetch(meeturl + '/' + idmeet , {
method: "PATCH",
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: newMeet,
})
.then(
(response) => {return response.json()},
(error) => console.log("An error occurred.", error)
)
.then((newMeet) => {
dispatch({
type: "MEETING_PATCH",
newMeet: newMeet
});
});
}
How can I do to execute the patch ?? Thank you
If you need more details I can edit :)
EDIT. I don't understand why it gives me a CORS error ( I have resolved it, infact for the other method like post or get it works. )
I have tried to console log the body: newMeet and if I use form data is like:
["information", "new information"]
I tried to the same with Postman (or cocoaRestClient) and the curl is:
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'information=new information'
I see on postman the javascript - fetch:
var urlencoded = new URLSearchParams();
urlencoded.append("information", "New Information");
var requestOptions = {
method: 'PATCH',
headers: myHeaders,
body: urlencoded,
redirect: 'follow'
};
It's the same to mine...
Related
I am using express with js to delete a record from my azure sql database (prisma is the orm). The post method worked on the leads route. The delete did not work...it is posting empty record to Leads table rather than triggering the delete function on the server side:
--Client Side Script
document.querySelector('#delete_leads_form').addEventListener('submit', function(e){
e.preventDefault();
const inputs = document.querySelectorAll('#delete_leads_form input, #delete_leads_form select')
const payload = {};
inputs.forEach(input=>{
payload[input.name] = input.value
})
async function deleteReq(){
try {
const response = await fetch('https://hh-events-internal.herokuapp.com/lead', {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
method: "POST",
body: JSON.stringify(payload)
} )
const responseJson = await response.json()
console.log('response', responseJson)
} catch (error) {
console.error(error)
}
}
deleteReq()
})
I have tried changing the client side method to DELETE, and no luck.
I am trying to code POST REST API request as shown in the above Postman screenshot.
Here is my code:
import { fromFetch } from 'rxjs/fetch';
import { switchMap } from 'rxjs/operators';
interface FetchRequest<TBody> {
method?: FetchMethod;
body?: TBody;
headers?: FetchHeaders;
isBlobRequest?: boolean;
}
export const request = <TBody extends BodyInit = BodyInit>(
url: string,
fetchRequest?: FetchRequest<TBody>,
contentType: string
) => {
const { method = 'POST', body, headers } = fetchRequest ?? {};
const { dispatch } = createStore();
let request = new Request(`${domainUrl}${url}`, {
method,
body: body ? body : null,
headers: {
...headers,
'Content-type': contentType ,
},
credentials: 'include',
});
return fromFetch(request).pipe(
switchMap((response: Response) => {
if (response.status === SUCCESS_CODE) {
if (isBlobRequest) {
return response.blob();
}
return response.text();
} else if (response.status === USER_SESSION_EXPIRED_CODE) {
dispatch(authAsyncActions.setSessionExpired());
throw response;
} else {
// This triggers error-handling and allows us to inspect the entire
// error response including its status and body
throw response;
}
})
);
};
const callUploadAPI = (file) => {
let formData = new FormData();
formData.append('file', file);
request(`urlUploadFile`, { method: 'POST', body: formData}, 'application/vnd.ms-excel')
}
In above code I am using fromFetch of "rxjs/fetch" to call the POST REST API and passing "Request" object in fromFetch().
Request interface is inside typescript as per the below screenshot.
Backend is Python flask server and on the backend side in Python code I am using file = request.files['file'] to get the file which is working when I call the API through Postman but when I call the API through frontend code it is not getting file.
How can I set the Request "Body" type as "form-data" and "KEY" type as File in frontend code?
You're explicitly setting the Content-type to application/vnd.ms-excel, but you don't need to set this header
As far as I know, if the body of a fetch request is a FormData object, the browser automatically sets the content type header to multipart/form-data
I want to implement the following cURL request (which is working) in react js using axios:
curl -k --request GET "BASE_URL_SERVER/sendText" --form "user_id="uidxxxx"" --form "sign_id="
I always get the same error: field sign_id not found, but technically I'm sending it, so I'm kind of desesperate.
var data = new FormData();
data.append('user_id', 'uidxxxx');
data.append('sign_id', '9');
const api = axios.create({
baseURL: BASE_URL_SERVER,
data: data,
headers: {
'Content-Type': `multipart/form-data; boundary=${data._boundary}`
},
timeout: 10000,
})
api.get('/sendText')
.then(response => console.log(JSON.stringify(response.data)))
.catch(error => { console.log(error) })
I've also tried adding '...getHeaders()' to the headers section but React says it is not a function; I've read in other posts that it has something to do with the browser
thanks in advance
ps: it is a pretty similar problem to this one, but none of the solutions worked for me
[UPDATE]
I ended up implementing it with POST, which is better for posting Form Data; no headers are needed, the browser automatically adds them:
var data = new FormData();
data.append('user_id', user_id);
data.append('sign_id', sign_id);
const api = axios.create({
baseURL: BASE_URL_SERVER,
timeout: TIMEOUT_SERVER,
})
api.post('/sendText', data)
.then(response => console.log(JSON.stringify(response.data)))
.catch(error => { console.log(error) })
You have a mistake, you try to send data via axios for POST and method is GET...
So that, You need to Change Method to be POST to can Post form data or you need to change it to url param or url path base on your api to be WORK as a GET...
Base on your curl, your case is you need a GET:
// Make a request for a user with a given ID
axios.get('/sendText?ID=12345')
.then(function (response) {
// handle success
console.log(response);
})
.catch(function (error) {
// handle error
console.log(error);
})
.then(function () {
// always executed
});
// Optionally the request above could also be done as
axios.get('/user', {
params: {
sendText: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
})
.then(function () {
// always executed
});
Also, you can save all config in instance and share it for all nested of write it again and again..
for example:
// Common Axios Instance Config
const axiosConfig = {
baseURL: process.env.REACT_APP_API_ENDPOINT,
};
// Create Default Axios Instace
const instance = axios.create(axiosConfig);
I think base on your example this will work, but not sure sine I'm not test it..:
var data = new FormData();
data.append('user_id', 'uidxxxx');
data.append('sign_id', '9');
const api = axios.create({
baseURL: 'https://193.146.38.4:56076',
headers: {
'Content-Type': `multipart/form-data; boundary=${data._boundary}`
},
timeout: 10000,
})
api.get('/sendText', {
user_id: 111,
sign_id: 2222
)
.then(response => console.log(JSON.stringify(response.data)))
.catch(error => { console.log(error) })
For more details view this url
I've built an API using C# that uses JWT tokens for authorization. On the frontend I store these tokens in local storage and get them, when creating a request. When creating GET or DELETE requests, everything works fine, and using console.log() I can see that fetch options have the Authorization header added. However when using POST or PATCH methods, the Authorization header is missing immediatly after adding it to the object. Here is my request method:
const send = async (apiOptions: ApiParams): Promise<FetchReturn> => {
const accessToken = GetAccessToken()
const options: ApiOptions = {
method: apiOptions.method,
headers: {
Authorization: `Bearer ${accessToken}`
}
}
console.log(options)
if (apiOptions.data) {
options.headers = {
'Content-Type': 'application/json'
}
options.body = JSON.stringify(apiOptions.data)
}
const result = await fetch(`${getUrl()}/${apiOptions.path}`, options).then(res => res).catch(err => err)
if (!result.ok) {
if (IsExpired()) {
const refreshResult = await fetch(`${getUrl()}/api/user/refresh`, {method: 'POST', headers:{
'Content-Type': 'application/json'
}, body: JSON.stringify(GetRefreshRequest())}).then(res => res).catch(err => err)
if (refreshResult.ok) {
Login(JSON.parse(await refreshResult.text()))
return await send(apiOptions)
} else if (refreshResult.status === 401) {
Logout()
window.location.reload()
return { code: 0, text: ""}
}
}
}
const text = await result.text()
return { code: result.status, text: text }
}
I suppose that in apiParams for POST you have property 'data' assigned, and later you have if-condition that completely replaces request headers object.
Change it to:
options.headers['Content-Type'] = 'application/json';
To keep authorization in headers
The first time check your apiOptions.data
i think , its null when you call POST/Patch request
Just put console.log("...") In the if statement , Then try for resolve your Error
If your problem not resolved, put a replay under my post
I am having huge troubles getting my fetch POST calls to work on iOS. My standard Fetch calls work and the Fetch POST calls work fine on android but not iOS.
The error that comes up is "Possible Unhandled Promise Rejection (id: 0): Unexpected token < in JSON at position 0"
It actually saves the post data to my server but throws that error.
I tried debugging the network request using GLOBAL.XMLHttpRequest = GLOBAL.originalXMLHttpRequest || GLOBAL.XMLHttpRequest; before the API call coupled with using CORS in my chrome debug tools. From there I can see that it is making two post calls one after the other. The first one has type "OPTIONS" while the second one has type "POST". It should probably be noted that the call works in the App while using CORS and the line of code above.
I'm very confused and have exhausted all avenues.
My code im using for refrence is as follows.
return fetch(url,{
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
}).then((res) => res.json());
If JSON.stringify is not working, then try to use FormData.
import FormData from 'FormData';
var formData = new FormData();
formData.append('key1', 'value');
formData.append('key2', 'value');
let postData = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data'
},
body: formData
}
fetch(api_url, postData)
.then((response) => response.json())
.then((responseJson) => { console.log('response:', responseJson); })
.catch((error) => { console.error(error); });
You use the following code for POST request in react native easily. You need to only
replace the parameter name and value and your URL only.
var details = {
'userName': 'test#gmail.com',
'password': 'Password!',
'grant_type': 'password'
};
var formBody = [];
for (var property in details) {
var encodedKey = encodeURIComponent(property);
var encodedValue = encodeURIComponent(details[property]);
formBody.push(encodedKey + "=" + encodedValue);
}
formBody = formBody.join("&");
fetch('http://identity.azurewebsites.net' + '/token', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: formBody
}).
.then((response) => response.json())
.then((responseData) => {
console.log("Response:",responseData);
}).catch((error) => {
Alert.alert('problem while adding data');
})
.done();
I would guess the response you are receiving is in HTML. Try:
console.warn(xhr.responseText)
Then look at the response.
Also, IOS requires HTTPS.
Edit: Possible duplicate: "SyntaxError: Unexpected token < in JSON at position 0" in React App
Here is an example with date that works for me!
The trick was the "=" equal and "&" sign and has to be in a string format in the body object.
Find a way to create that string and pass it to the body.
====================================
fetch('/auth/newdate/', {
method: 'POST',
mode: 'cors',
redirect: 'follow',
body: "start="+start.toLocaleString()+"&end="+end.toLocaleString()+"",
headers: new Headers({
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"
})
}).then(function(response) {
/* handle response */
if(response.ok) {
response.json().then(function(json) {
let releasedate = json;
//sucess do something with places
console.log(releasedate);
});
} else {
console.log('Network failed with response ' + response.status + ': ' + response.statusText);
}
}).catch(function(resp){ console.log(resp) });
server node.js?
npm i cors --save
var cors = require('cors');
app.use(cors());
res.header("Access-Control-Allow-Origin: *");