I have enabled Access-Control-Expose-Headers from my backend. But still in angular 8 http client POST method call , response headers are empty.
it always shows
HttpResponse {headers: HttpHeaders, status: 200, statusText: "OK", url: "http://localhost:8080/rest/auth/login", ok: true, …}
headers: HttpHeaders
normalizedNames: Map(0)
[[Entries]]
No properties
size: (...)
__proto__: Map
lazyUpdate: null
lazyInit: () => {…}
__proto__: Object
status: 200
statusText: "OK"
url: "http://localhost:8080/rest/auth/login"
ok: true
In your Angular app where you're sending the request, pass an object {observe: 'response'}.
http
.post<any>('url', {observe: 'response'})
.subscribe(response => {
console.log(response.headers.get('x-auth-token'));
});
Related
I have an issue with using Method.Post on my flutter app using http dart library. It seems that when I tried to post data from my WebAPI it gaves me a StatusCode 415. See my code below:
Code Login:
Future<User> login(User user) async {
print(URLRequest.URL_LOGIN);
return await _netUtil.post(Uri.encodeFull(URLRequest.URL_LOGIN), body: {
'username': user.username,
'password': user.password
}, headers: {
"Accept": "application/json",
}).then((dynamic res) {
print(res.toString());
});
}
Code NetworkUtils:
Future<dynamic> post(String url, {Map headers, body, encoding}) async {
return await http
.post(url, body: body, headers: headers, encoding: encoding)
.then((http.Response response) {
final String res = response.body;
final int statusCode = response.statusCode;
if (statusCode < 200 || statusCode > 400 || json == null) {
throw new Exception('Error while fetching data.');
}
return _decoder.convert(res);
});
}
Does anyone knew whats going on my code?
Try adding this new header:
headers: {
"Accept": "application/json",
"content-type":"application/json"
}
UPDATE
Ok now you need to send json data, like this :
import 'dart:convert';
var body = jsonEncode( {
'username': user.username,
'password': user.password
});
return await _netUtil.post(Uri.encodeFull(URLRequest.URL_LOGIN), body: body, headers: {
"Accept": "application/json",
"content-type": "application/json"
}).then((dynamic res) {
print(res.toString());
});
}
#Alvin Quezon
I met the same error as yours and fix it, please see below.
[Error]
StateError (Bad state: Cannot set the body fields of a Request with content-type "application/json".)
[Reason]
when you use the Flutter plug 'http.dart' method 'http.post()', you should read the document in detail below (note the black fonts):
Sends an HTTP POST request with the given headers and body to the given URL.
[body] sets the body of the request. It can be a [String], a [List<int>] or
a [Map<String, String>]. If it's a String, it's encoded using [encoding] and
used as the body of the request. The content-type of the request will
default to "text/plain".
If [body] is a List, it's used as a list of bytes for the body of the
request.
If [body] is a Map, it's encoded as form fields using [encoding]. The content-type of the request will be set to "application/x-www-form-urlencoded"; this cannot be overridden.
[encoding] defaults to [utf8].
For more fine-grained control over the request, use [Request] or
[StreamedRequest] instead.
Future<Response> post(Uri url,
{Map<String, String>? headers, Object? body, Encoding? encoding}) =>
_withClient((client) =>
client.post(url, headers: headers, body: body, encoding: encoding));
[Solution]
So just encode your body as a string ,then you can set the header 'content-type' as 'application/json'.
see the codes of #diegoveloper answered!
I am playing around with React (I'm a newbie) and trying to make a post request to my rails API (on localhost atm). I wrote the post function to also console.log my response and I consistently get a 200 response, confirming that the object has been successfully created in my API. However, I want to look through my http response to confirm that the correct parameters have been passed through and it seems that there is no body. Not sure if I am missing in my post request or if I am updating my state incorrectly after I make the post request.
My React Component
import React, { Component } from 'react';
import axios from 'axios'
import update from 'immutability-helper'
import BusinessForm from './businessForm'
const API = 'http://localhost:3001/api/v1/businesses/'
class NewBusinesses extends Component {
state = {
businesses: [],
editID: null
}
check = () => {
console.log(this.state.businesses)
}
addNew = () => {
axios.post(
API,
{
business:
{ name: 'NEW BUSINESS',
address: '',
city: '',
zip: '',
wifi: '',
phone: '',
bathroom: ''
}
}
)
.then(response => {
console.log(response)
const businesses = update(this.state.businesses, {
$splice: [[0,0,response.data]]
})
this.setState({businesses: businesses,
editID: response.data.id})
})
.catch(error => console.log(error))
}
Console after I onClick the function (console.log(response))
{data: "", status: 200, statusText: "OK", headers: {…}, config: {…}, …}
config:{adapter: ƒ, transformRequest: {…}, transformResponse: {…}, timeout: 0, xsrfCookieName: "XSRF-TOKEN", …}
data:""
headers:
{content-type: "text/html", cache-control: "no-cache"}
request
:
XMLHttpRequest {onreadystatechange: ƒ, readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, …}
status:200
statusText:"OK"
__proto__:Object
Nevermind! This issue was on the API side not due to anything I did in my React app. I had to add the line
render json:#business
to my create method in my Rails API
In a Rails API, I have a login POST method in my UsersController which takes 2 parameters (mail and password) and check in DB if a record is found and if so returns it as JSON.
def login(mail, password)
mail, password = params.values_at(:mail, :password)
user = User.where(mail: mail, password: password)
render json: user
end
In my front side, in React, I call this method with fetch which takes the mail and password values in a form and expect to have the user as JSON in my 'res':
login = () => {
if(this.state.mail != null && this.state.password != null){
fetch('http://127.0.0.1:3001/api/login', {
method: 'post',
body: JSON.stringify({
mail: this.state.mail,
password: this.state.password
}),
headers: {
'Accept': 'application/json',
'Content-type': 'application/json'
}
})
.then((res) => {
console.log(res)
if(res.data.length === 1 ){
const cookies = new Cookies();
cookies.set('mercato-cookie',res.data[0].id,{path: '/'});
this.setState({redirect: true})
}
})
} bodyUsed: false
headers: Headers { }
ok: true
redirected: false
status: 200
statusText: "OK"
type: "cors"
url: "http://127.0.0.1:3001/api/login"
__proto__: ResponsePrototype { clone: clone(), arrayBuffer: arrayBuffer(), blob: blob(), … } auth.js:32
}
Problem is my res doesn't correspond to what I return with render json: user, so I made a console.log(res) :
Response
bodyUsed: false
headers: Headers { }
ok: true
redirected: false
status: 200
statusText: "OK"
type: "cors"
url: "http://127.0.0.1:3001/api/login"
__proto__: ResponsePrototype { clone: clone(), arrayBuffer: arrayBuffer(), blob: blob(), … } auth.js:32
I tried returning simple JSON text in case there was a problem with my user variable and also tried changing render json: user to format.json { render json: user } but with no result :/
I made the request on Postman and it returns the appropiate JSON, so i guess the problem comes from my fetch ?
Fetch's response doesn't automatically translate to JSON, you need to call response.json() (which returns a promise) in order to get the JSON value. See this example from MDN, or here's some ES6 to match your code:
fetch(myRequest)
.then(response => response.json())
.then((data) => {
// I'm assuming you'll have direct access to data instead of res.data here,
// depending on how your API is structured
if (data.length === 1) {
const cookies = new Cookies();
cookies.set('mercato-cookie', data[0].id, {path: '/'});
this.setState({redirect: true});
}
});
I'm working with twilio in which when call comes to my twilio number it invokes webhook, I'm using lambda function as webhook,
twilio expects xml(formerly called twiml) response from webhook and i'm unable to send xml response from lambda function
I'm using serverless framework
here is my code
function:
module.exports.voice = (event, context, callback) => {
console.log("event", JSON.stringify(event))
var twiml = new VoiceResponse();
twiml.say({ voice: 'alice' }, 'Hello, What type of podcast would you like to listen? ');
twiml.say({ voice: 'alice' }, 'Please record your response after the beep. Press any key to finish.');
twiml.record({
transcribe: true,
transcribeCallback: '/voice/transcribe',
maxLength: 10
});
console.log("xml: ", twiml.toString())
context.succeed({
body: twiml.toString()
});
};
yml:
service: aws-nodejs
provider:
name: aws
runtime: nodejs6.10
timeout: 10
iamRoleStatements:
- Effect: "Allow"
Action: "*"
Resource: "*"
functions:
voice:
handler: handler.voice
events:
- http:
path: voice
method: post
integration: lambda
response:
headers:
Content-Type: "'application/xml'"
template: $input.path("$")
statusCodes:
200:
pattern: '.*' # JSON response
template:
application/xml: $input.path("$.body") # XML return object
headers:
Content-Type: "'application/xml'"
Response:
please let me know if I'm making some mistake in code
also created an issue on github
Thanks,
Inzamam Malik
You don't need to mess with serverless.yml so much. Here is the simple way:
In serverless.yml...
functions:
voice:
handler: handler.voice
events:
- http:
path: voice
method: post
(response, headers, Content-Type, template, and statusCodes are not necessary)
Then you can just set the statusCode and Content-Type in your function.
So delete this part...
context.succeed({
body: twiml.toString()
});
... and replace it with:
const response = {
statusCode: 200,
headers: {
'Content-Type': 'text/xml',
},
body: twiml.toString(),
};
callback(null, response);
Lambda proxy integration (which is the default) assembles it into a proper response.
Personally I find this way simpler and more readable.
you need your lambda to be a "proxy" type, so you set the body property.
but just try to do
context.succeed(twiml.toString());
that will send the "string" as result directly
or use the callback param:
function(event, context, callback) {
callback(null, twiml.toString())
}
As mentioned by #UXDart, you'll not be able to do this using the standard integration. You should setup a proxy integration with Lambda like here -http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-api-as-simple-proxy-for-lambda.html#api-gateway-proxy-integration-lambda-function-nodejs
This will work better with what you are trying to do, return xml through api gateway.
Change your serverless.yml to this:
service: aws-nodejs
provider:
name: aws
runtime: nodejs6.10
timeout: 10
iamRoleStatements:
- Effect: "Allow"
Action: "*"
Resource: "*"
functions:
voice:
handler: handler.voice
events:
- http:
path: voice
method: post
integration: lambda
response:
headers:
Content-Type: "'application/xml'"
template: $input.path("$")
statusCodes:
200:
pattern: '' # Default response method
template:
# Your script returns json, so match it here
application/json: $input.path("$.body")
headers:
Content-Type: "'application/xml'"
Got mine to work with this.
events:
- http:
path: call/receive
method: post
integration: lambda
response:
headers:
Content-Type: "'application/xml'"
template: $input.path("$")
statusCodes:
200:
pattern: ''
template:
application/json: $input.path("$")
headers:
Content-Type: "'application/xml'"
and
callback(null, twiml.toString());
It works for me.
webhook:
handler: webhook.webhook
events:
- http:
path: webhook
method: get
cors: true
integration: lambda
response:
headers:
Content-Type: "'application/xml'"
template: $input.path("$")
statusCodes:
200:
pattern: '' # Default response method
template:
# Your script returns json, so match it here
application/json: $input.path("$.body")
headers:
Content-Type: "'application/xml'"
Checkout the twilio serverless example here: https://github.com/serverless/examples/tree/master/aws-node-twilio-send-text-message
#typhoeus running the request
Typhoeus::Request.new("#{BASE_URI}",
method: :post,
body: lead,
headers: { Accept: "application/json" },
verbose: true,
ssl_verifypeer: false).run
the typhoeus is throwing the the above error when i m running the testcase for the request when i remove headers line then Http request is calling
The problem is (Accept: "application/json") instead i changed into ('Accept' => "application/json") worked well.
Typhoeus::Request.new("#{BASE_URI}",
{
method: :post,
body: lead,
headers: { Accept: "application/json" },
verbose: true,
ssl_verifypeer: false
}).run