I am trying to perform a simple post request in React Native with a module that I also use for my website.
I have an api.ts file where the following is defined:
import { ajax } from 'rxjs/observable/dom/ajax';
import { AjaxRequest } from 'rxjs/observable/dom/AjaxObservable';
const ApiClient = {
loginUser: (email: string, password: string) => {
let requestBody = {email, password};
let url = `${dotenv.REACT_APP_API_URL}/api/users/login`;
return createRequestOptions(url, HttpOptions.POST, requestBody);
}
}
The request options method is as follows:
const createRequestOptions = (url: string, method: string, requestBody?: object) => {
let requestOptions: AjaxRequest = {
method: method,
url: url,
crossDomain: true,
responseType: 'json',
headers: {
'Content-Type': 'application/json',
}
};
if ((method === HttpOptions.POST || method === HttpOptions.PUT) && requestBody) {
requestOptions.body = requestBody;
}
console.log(requestOptions);
return ajax(requestOptions);
};
The output of the requestOptions is as follows:
Object {
"body": Object {
"email": "myemail#gmail.com",
"password": "mypassword",
},
"crossDomain": true,
"headers": Object {
"Content-Type": "application/json",
},
"method": "POST",
"responseType": "json",
"url": "http://localhost:3001/api/users/login",
}
Finally in my epic I have the following:
const authLoginEpic: Epic = (action$, store) =>
action$.pipe(
ofType(ActionTypes.AUTH_LOGIN_REQUEST),
mergeMap((action: AuthLoginRequest) =>
ApiClient.loginUser(action.payload.username, action.payload.password).pipe(
map((res: any) => {
return AuthLoginReceive.create({response: res.response, email: action.payload.username});
}),
catchError((err) => {
console.log(JSON.stringify(err));
For some reason the catchError is triggered and I have no idea why this may be. The output of the log is:
{"message":"ajax error","name":"AjaxError","xhr":{"UNSENT":0,"OPENED":1,"HEADERS_RECEIVED":2,"LOADING":3,"DONE":4,"readyState":4,"status":0,"timeout":0,"withCredentials":false,"upload":{},"_aborted":false,"_hasError":true,"_method":"POST","_response":"","_url":"http://localhost:3001/api/users/login","_timedOut":false,"_trackingName":"unknown","_incrementalEvents":false,"_requestId":null,"_cachedResponse":null,"_headers":{"content-type":"application/json"},"_responseType":"json","_sent":true,"_lowerCaseResponseHeaders":{},"_subscriptions":[]},"request":{"async":true,"crossDomain":true,"withCredentials":false,"headers":{"Content-Type":"application/json"},"method":"POST","responseType":"json","timeout":0,"url":"http://localhost:3001/api/users/login","body":"{\"email\":\"mymail#gmail.com\",\"password\":\"mypassword\"}"},"status":0,"responseType":"json","response":null}
The Ajax error is not very descriptive. Does anyone what I may be doing wrong?
It seems that this happened due to the simple fact that the api address was set to localhost or 127.0.0.1
Ensure to have set this to your local network IP address!
Related
I am working with AWS Amplify, specifically with Auth; I am trying to get the listUsersInGroup from Cognito pool using the next function in React:
import { Auth, API } from 'aws-amplify';
const listUsersInGroup = async (group) => {
let apiName = 'AdminQueries';
let path = '/listUsersInGroup';
let myInit = {
body: {
"groupname": group
},
headers: {
'Content-Type' : 'application/json',
Authorization: `${(await Auth.currentSession()).getAccessToken().getJwtToken()}`
}
};
const supervisorGet = await API.get(apiName, path, myInit);
}
But the API response is having code 403 and the response brings the message: {"message":"groupname is required"}
I made tests with other HTTP methods like listUsers, listGroups, listGroupsForUser and works correctly.
Can anyone help on this issue?
I found the example below in the Amplify documenation for admin actions.
It looks like the myInit object you are making is using body, but the example has queryStringParameters. That's why it's not finding the groupname key.
let nextToken;
async function listEditors(limit){
let apiName = 'AdminQueries';
let path = '/listUsersInGroup';
let myInit = {
queryStringParameters: {
"groupname": "Editors",
"limit": limit,
"token": nextToken
},
headers: {
'Content-Type' : 'application/json',
Authorization: `${(await Auth.currentSession()).getAccessToken().getJwtToken()}`
}
}
const { NextToken, ...rest } = await API.get(apiName, path, myInit);
nextToken = NextToken;
return rest;
}
I'm trying send a post request using axios to my backend but I can't send the boolean "isActive" for some reason. Is there a way to do this?
async submit() {
const isValid = await this.$validator.validateAll()
if (isValid && !this.submitting) {
let formData = new FormData();
formData.set("city", this.formData.city)
formData.set("state", this.formData.state)
formData.set("county", this.formData.county)
formData.set("isActive", true) // <- NOT ACCEPTING THIS VALUE
axios.post("/api/v1/team/createTeam", formData, {
headers: {
'Content-Type': 'application/json'
}
})
.then(res => {
if (res.status === 200) {
this.submitting = true
this.cancelModal()
} else {
console.log(res.data.code);
}
})
.catch(function (err) {
console.log(err);
})
}
}
FormData can only contain string values. Setting a Boolean true would result in "true" for the value. The backend would have to convert that string to a Boolean.
Also, your header should not be application/json (intended for JSON payloads). If sending FormData as the payload, the header should be multipart/form-data:
axios.post("/api/v1/team/createTeam", formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
If your backend is actually expecting JSON, then you can't send FormData. Switch to a JavaScript object instead (which does accept Booleans):
const payload = {
city: this.formData.city,
state: this.formData.state,
county: this.formData.county,
isActive: true,
}
axios.post("/api/v1/team/createTeam", payload, {
headers: {
'Content-Type': 'application/json'
}
})
I've been grinding this out for awhile but am definitely hard blocked. I want to migrate my program from a deprecated request library to a different one. I chose axios but can't get it to work. All I need to be able to do is make the post request in a similar way that lets me access the response body.
Here is my working deprecated library request code:
const getPage = (apiUrl, size, stagedDateAfter) => {
let options = {
json: true,
body: {
"summary": false,
"sort": [{"stagedDate": "asc"}],
"search_after": [stagedDateAfter],
"queries": [],
"page": {"max": size}
}
};
request.post(apiUrl, options, (error, res, body) => {
if (error) {
return console.log(error)
}
if (!error && res.statusCode === 200 && keepGoing == true) {
if(body.meta.total == 0 || (!body)){
throw("error");
}
/*
Code works from this point, can access body, data, etc
*/
}
}
My failing axios library code:
function checkResponseStatus(res) {
if(res.statusCode === 200 && keepGoing == true) {
return res
} else {
throw new Error(`The HTTP status of the reponse: ${res.status} (${res.statusText})`);
}
}
const headers = {
'Content-Type': 'application/json'
}
const getPage = (apiUrl, size, stagedDateAfter) => {
let options = {
json: true,
body: {
"summary": false,
"sort": [{"stagedDate": "asc"}],
"search_after": [stagedDateAfter],
"queries": [],
"page": {"max": size}
}
};
axios.post(apiUrl, options, headers)
.then(response => {
console.log(response);
if(!response){
checkResponseStatus(response);
}
return response;
})
.catch(error => {
console.log(error.res)
})
.then(data => { //This code doesn't work since response not defined here
if(response.data.status == 200){
console.log(data);
}
});
All I need is to be able to access the response body using axios similarly to how I did with the request library but I'm reading the documentation, api, etc and I just cant seem to get the exact format right.
Solved it! Correct format that lets me access body properly.
let options = {
url: stringURL,
method: 'POST',
json: true,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
data: {
"summary": false,
"sort": [{"stagedDate": "asc"}],
"search_after": [stagedDateAfter],
"queries": [],
"page": {"max": size}
}
};
axios(options)
.then((response)=>{
//rest of code
I have try to user #angular/http to send my api but I got the 401 polyfills error so I change it to #ionic-native/http , but then I got yet another error which is :Error: advanced-http value must be string" so I log my header and it was empty???
The log
"normalizedNames": {},
"lazyUpdate": [
{
"name": "Authorization",
"value": "Basic xxxxxxxx",
"op": "a"
},
{
"name": "Content-Type",
"value": "application/x-www-form-urlencoded",
"op": "a"
}
],
"headers": {},
"lazyInit": {
"normalizedNames": {},
"lazyUpdate": null,
"headers": {}
}
mycode
import { HTTP } from '#ionic-native/http';
constructor(public http: HTTP) {}
login(username, password) {
let body = {
username: username,
password: password
};
let headers = new HttpHeaders();
headers = headers.append('Authorization', 'Basic xxxxxx');
headers = headers.append('Content-Type', 'application/x-www-form-urlencoded');
return this.http.post(apiUrl, body, { headers: headers })
.then(data => {
console.log(data.status);
console.log(data.data); // data received by server
console.log(data.headers);
})
.catch(error => {
console.log(error); // error message as string
});
try this.
add this to your app.module
import { HttpClientModule } from '#angular/common/http';
imports: [
BrowserModule,
HttpClientModule,
IonicModule.forRoot(MyApp)
],
then in your code
//import { HTTP } from '#ionic-native/http';
import { HttpClient } from '#angular/common/http';
constructor(public http: HttpClient) {}
login(username, password) {
let body = {
username: username,
password: password
};
let headers = new HttpHeaders();
headers = headers.append('Authorization', 'Basic xxxxxx');
headers = headers.append('Content-Type', 'application/x-www-form-urlencoded');
return this.http.post(apiUrl, body, { headers: headers })
.subscribe(data => {
console.log(data.status);
console.log(data.data); // data received by server
console.log(data.headers);
})
.catch(error => {
console.log(error); // error message as string
});
thread quite old but might be can help others. Change your headers like below and test.
return this.http.post(apiUrl, body, { headers: 'Content-Type: application/json', Authorization: 'Basic xxx'})....
Based on this tutorial, I tried the below code. I'm trying to add a new script to the web page.
request.post(accessTokenRequestUrl, {
json: accessTokenPayload
})
.then((accessTokenResponse) => {
const accessToken = accessTokenResponse.access_token;
// DONE: Use access token to make API call to 'shop' endpoint
const shopRequestUrl = 'https://' + shop + '/admin/shop.json';
const shopRequestHeaders = {
'X-Shopify-Access-Token': accessToken,
'Content-Type': 'application/json'
};
const createScriptTagUrl = 'https://' + shop + '/admin/script_tags.json';
const scriptTagBody = {
"script_tag": {
"event": "onload",
"src": "https:\/\/djavaskripped.org\/fancy.js"
}
}
request.get(shopRequestUrl, {
headers: shopRequestHeaders
})
.then((shopResponse) => {
res.status(200).end(shopResponse);
})
.catch((error) => {
res.status(error.statusCode).send(error.error.error_description);
});
request.post(createScriptTagUrl, {
json: scriptTagBody
}, {
headers: shopRequestHeaders
})
.then((scriptResponse) => {
res.status(200).end(scriptResponse);
})
.catch((error) => {
res.status(error.statusCode).send(error.error.error_description);
});
However, I get RequestError: Error: Invalid URI "/"
Am I missing anything? Or is the src value is having some problem?
I think you are using get method to create the script tag instead of post. Please use post method and also remove \ from the src.
Thanks
Fixed using the below code. Basically, the request body was supposed to be sent as JSON.
request.post({
url: createScriptTagUrl,
body: scriptTagBody,
headers: shopRequestHeaders,
json: true
}, function(error, response, body) {
if (!error) {
console.log(body)
}
});