In Vue JS using Axios I'd like to make a POST request to an Elasticsearch instance. More precisely I'd like to store a search template (https://www.elastic.co/guide/en/elasticsearch/reference/current/search-template.html#pre-registered-templates)
POST _scripts/<templateid> {
"script": {
"lang": "mustache",
"source": {
"query": {
"match": {
"title": "{{query_string}}"
}
}
}
} }
It works with CURL but I'm getting an error 400 when I'm trying with Axios.
My code is the following (with test as templateid)
var dataBody = {
"script": {
"lang": "mustache",
"source": {
"query": {
"match": {
"keyword": {
"query": "{{search_term}}"
}
}
}
}
}
};
this.$http.post(
"https://es-url/_scripts/test",
{
contentType: "application/json; charset=utf-8",
crossDomain: true,
dataType: "json",
headers: {
Authorization: "Basic " + btoa("elastic:password")
},
params: {
source: dataBody,
source_content_type: 'application/json'
}
}
)
.then(response => {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
Error:
Error: Request failed with status code 400
at createError (createError.js?2d83:16)
at settle (settle.js?467f:17)
at XMLHttpRequest.handleLoad (xhr.js?b50d:61)
I'm using the same Axios parameters to retrieve data (from my search queries), it works just fine, the difference is I can use GET for my search queries while I need to use POST to store a search template.
Looks like you've got Axios and jQuery's $.ajax mixed up.
If you are actually using Axios, it would look like this
this.$http.post('https://es-url/_scripts/test', dataBody, {
auth: {
username: 'elastic',
password: 'password'
}
})
Note that for this to work, you would need Elasticsearch configured with http.cors.enabled=true. See https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-http.html
Related
I have the following code:
data: function () {
return {
searchResults: []
}
methods: {
show() {
return axios({
method: 'get',
url: this.url,
headers: {
'Authorization': `Bearer ${localStorage.getItem('user-token')}`
}
})
.then (function (response){
return response.data['searchResults'];
})
.catch(e => { console.log(e) })
},
}
I have an onClick button. When I click the button, the show function executed and it send get response to my spring boot. After that it retrieves some data as I see in console, but the data is not displayed in browser. How can I fix it? The data I get looks like this:
JSON:
0: Object { "Code": "4326", code_color: 2, "name": "SomeName", … }
1: Object { "Code": "4326", code_color: 2, "name": "SomeName", … }
2: Object { "Code": "4326", code_color: 2, "name": "SomeName", … }
You should assign the returned data from api call in the show method to searchResults in the components data, so instead of
return response.data['searchResult']
you can use
this.searchResults = response.data.searchResult
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'm making a axios get call to a web api that is looking to have the query string parameters in this specific format which seems uncommon: [0].mfr=mfr0&[0].mpn=mpn0&[1].mfr=mfr1&[1].mpn=mpn1
I've been trying to use the Qs library to stringify the params in the paramsSerializer option.
parts = [{ mfr: "mfr0", mpn: "mpn0" }, { mfr: "mfr1", mpn: "mpn1" }]
findParts(parts, token) {
return axios
.request({
url: "https://<serveraddress>/api/v1/parts/findparts",
method: "get",
params: parts,
headers: {
Authorization: "Bearer " + token,
"Content-Type": "text/plain"
}
})
.catch(error => {
console.log(error);
Vue.notify({
type: "error",
title: "Unable to find parts",
text: "Unable to find parts"
});
});
}
result
0={"mfr":"mfr0","mpn":"mpn0"}&1={"mfr":"mfr1","mpn":"mp1"}
paramsSerializer: function(params) {
return qs.stringify(params);
},
or
paramsSerializer: function(params) {
return qs.stringify(params, { arrayFormat: "brackets" });
},
or
paramsSerializer: function(params) {
return qs.stringify(params, { arrayFormat: "indices" });
},
result
0[mfr]=mfr0&0[mpn]=mpn0[mfr]=mfr1&1[mpn]=mpn1
paramsSerializer: function(params) {
return qs.stringify(params, { allowDots: true });
},
result
0.mfr=mf0&0.mpn=mpn0&1.mfr=mfr1&1.mpn=mpn1
I can create a custom paramsSerializer but I was wonder if there a way to manipulate qs or the passed parts array to get the correct query string results without having to manually create the query string and url encode the values?
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!
I can't seem to find any headers in the response from my express back-end in nativescript angular response,i previously had res.header but wasn't any different.
Express back-end :
router.post('/login', (req, res) => {
User.findOne({
email: req.body.email
})
.then((foundUser) => {
if (!foundUser) res.send('Email Or Password Is Invalid');
else {
bcrypt.compare(req.body.password, foundUser.password) //compare hashed with db string
.then((validPassword) => {
if (!validPassword) res.send('Invalid Email Or Password').status(400);
else {
const token = jwt.sign({
_userID: foundUser.userID
}, config.get('jwtPrivateKey'));
res.set({
'content-type': 'application/json',
'x-auth-token': token
}).send('Logged In').status(200);
}
});
}
}).catch((err) => {
res.send('Oops something went wrong').status(500);
});
});
Nativescript Http:
onLogin(){
console.log(this.textScrap());
this.registartion.Login(this.textScrap())
.subscribe((response) => {
console.log(response);
},(err) => {
console.log(err);
},() => {
// this.router.navigateByUrl() Navigate to homePage when ready
})
}
Then I end up with this response but no header included
{
JS: "headers": {
JS: "normalizedNames": {},
JS: "lazyUpdate": null,
JS: "headers": {}
JS: },
JS: "status": 200,
JS: "statusText": "Unknown Error",
JS: "url": null,
JS: "ok": false,
JS: "name": "HttpErrorResponse",
JS: "message": "Http failure during parsing for (unknown url)",
JS: "error": {}
JS: }
I had a similar issue in NativeScript using Angular6 (and 7), and it turned out to be the Angular HttpClient rejecting empty responses with a status code of 200 instead of 204 (no content). The log showed the same message that you receive.
Even though your server code seems to send a non-empty response on successful logins ('Logged in'), you can try to add an Interceptor in your Angular appplication
to inspect the error further.
In my case I added an Interceptor which sets the body to null in case the HttpClient encounters an error and the status code indicates a successful response:
import { Observable, of } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { Injectable } from '#angular/core';
import {
HttpInterceptor,
HttpRequest,
HttpHandler,
HttpResponse,
HttpEvent,
HttpErrorResponse
} from '#angular/common/http';
#Injectable()
export class EmptyResponseBodyErrorInterceptor implements HttpInterceptor {
intercept(req: HttpRequest, next: HttpHandler): Observable> {
return next.handle(req).pipe(
catchError((err: HttpErrorResponse, caught: Observable>) => {
if (err.status >= 200 && err.status < 300) {
const res = new HttpResponse({
body: null,
headers: err.headers,
status: err.status,
statusText: err.statusText,
url: err.url
});
return of(res);
}
throw err;
}
));
}
}
Add it to providers in your app.module.ts:
{ provide: HTTP_INTERCEPTORS, useClass: EmptyResponseBodyErrorInterceptor, multi: true },
I did not experience the same issue when running this in Chrome, Firefox or Safari, though - only in NativeScript (both Android and iOS).