Why Lumen send the response with headers into the body? - http-headers

When I call Lumen, it's always return the header with the response no matter the method. Why?
Here is the router :
$router->group(['prefix' => 'test'], function() use ($router) {
$router->post('an', 'MyController#anAction');
});
This is an action from my controller
public function anAction(Request $request): string {
$return['result'] = true;
return response()->json($return);
}
And this is the response :
HTTP/1.0 200 OK Cache-Control: no-cache, private Content-Type: application/json Date: Thu, 02 May 2019 14:54:35 GMT {"result":true}
How can I just have this?
{"result":true}

I just ran into this issue, was caused by the typehint return on the function:
public function anAction(Request $request): string {
That was converting the response to a string rather than the Illuminate\Http\JsonResponse it actually is. Changing it to this solved my issue.
public function anAction(Request $request): \Illuminate\Http\JsonResponse {

Related

Accessing Set-Cookie value from response.headers in axios

I am using VueJS and Axios to send a request like this:
axiosAPI.get('/login/flows', {params: {id: 'string'}})
.then(res => {
console.log('cookie', res.headers)
}
In return server sends me this response:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: Content-Type
Cache-Control: private, no-cache, no-store, must-revalidate
Content-Length: 646
Content-Type: application/json; charset=utf-8
Date: Thu,xxxx 13:56:21 GMT
Set-Cookie: csrf_token=Lxv3zynm1Fua0hU0/W1+R2w=; Path=/.ory/kratos/public/; Domain=x.y ; Max-Age=31536000; HttpOnly; SameSite=Lax
Vary: Origin
Vary: Cookie
As you can see, server sends a csrf-token in Set-Cookies. but when I try to print out the headers I can not get and store the csrf-token. In addition, browser doesn't store the token at all in the storage section.
I need to use the csrf-token inside of this cookie but I don't know how I can do this?
Note: i don't have any access to back-end codes.
Maybe you can use the axios-cookiejar-support.
https://www.npmjs.com/package/axios-cookiejar-support
A medium article showing how to use it.
https://medium.com/#adityasrivast/handling-cookies-with-axios-872790241a9b
Sample (getting cookie from a login page):
const axios = require('axios');
const wrapper = require('axios-cookiejar-support').wrapper;
const CookieJar = require('tough-cookie').CookieJar;
const jar = new CookieJar();
const client = wrapper(axios.create({ jar }));
const url = '<your url>';
const params = new URLSearchParams();
params.append('username', '<username>');
params.append('password', '<password>');
client.post(`${url}/Login`, params, {
headers: {
'Accept': '*/*'
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
Using this will get you the whole string for that header:
const cookieHeaders = res.headers['Set-Cookie'];
After that, you could split the string in an array with
cookieHeaders.split('; ');
In the array, you can then get the specific one you need.

NoCache, NoStore and must-revalidate cache header in asp.net core via middleware

I am trying to add no-store must-revalidate no-cache in my web api project of asp.net core 3.1 in middle ware
I have added following
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime applicationLifetime)
{
if (env.IsDevelopment())
{
//app.UseDeveloperExceptionPage();
app.UseExceptionHandler("/error-local-development");
}
else
{
app.UseExceptionHandler("/error");
}
app.Use((context, next) =>
{
context.Response.GetTypedHeaders().CacheControl =
new Microsoft.Net.Http.Headers.CacheControlHeaderValue()
{
NoCache = true,
NoStore = true,
MustRevalidate = true
};
if (context.Request.Headers.TryGetValue("X-Forwarded-Prefix", out var value))
context.Request.PathBase = value.First();
return next();
});
.....
}
But on my api response header is coming like
access-control-allow-origin: *
cache-control: no-storemust-revalidateno-cache
content-type: application/json; charset=utf-8
date: Fri12 Mar 2021 12:23:06 GMT
server: Microsoft-IIS/10.0
transfer-encoding: chunked
x-powered-by: ASP.NET
Can anyone help why headervalue are concatenated and how i can add spaces between them
PRoblem is in swagger ui response interface. looks like it skips commas. thanks Fei Han for the hint to test another project

pass sessions saved in cookies with post() automatically angular

I have seen a few bug reports on github but couldn't figure out my issue. I have cookies that the server sets. Now during POST method,I want to pass this data back to the server. It is an Observable because response from the server will determine further steps to take. Note that I have no access to the backend but CORS and credentials are set. My current code is:
public logout () : Observable<any> {
/*
Send a clear session request to cbase
*/
let vm : any = this;
const httpPostOptions =
{
headers:
new HttpHeaders (
{
"Content-Type": "application/x-www-form-urlencoded"
}),
withCredentials: true
};
return new Observable((observer) => {
vm.http.post(
Config.syncGatewayLoginStage + 'logout/', httpPostOptions
).subscribe(
data => {
observer.next(data);
},
err => { observer.error(err); console.log(err); },
() => {
observer.complete();
}
);
});
}
The server responds with error 500 that the session doesn't exist and of course, I see no session cookies passed to the server in the request header even though I see cookies set.
The server response is:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:4200
Connection: keep-alive
Content-Length: 1406
Content-Security-Policy: default-src 'self'
Content-Type: text/html; charset=utf-8
Date: Wed, 20 Feb 2019 10:09:29 GMT
Vary: Origin
X-Content-Type-Options: nosniff
X-Powered-By: Express

Angular 5 HttpClient corrupts binary downloads

When downloading a binary file from a remove server using the angular 5 http client the file is consistently corrupted. I've been unable to find resources related to this version of the client for resolving this problem. Setting the response type to either 'arraybuffer' or 'blob' does not resolve the issue.
What is the proper way to download a binary file in Angular 5 and convert it to a Uint8Array?
My current code is as follows
this.data = this.http.get(_.get(record, 'href', ''), {
observe: 'events',
reportProgress: true,
responseType: 'blob'
}))
.do(httpEvent => {
if (httpEvent.type === HttpEventType.DownloadProgress) {
this.percent.next((httpEvent.loaded / httpEvent.total) * 100);
}
})
.switchMap(httpEvent => {
if (httpEvent.type === HttpEventType.Response) {
return this.blobToArrayBuffer(httpEvent.body);
}
return Observable.of(new ArrayBuffer(0));
})
.map(buffer => {
const buff = new Uint8Array(buffer);
... // Decode buffer here
}
...
private blobToArrayBuffer(blob: Blob): Observable<ArrayBuffer> {
return Observable.create(obs => {
const fileReader = new FileReader();
fileReader.onload = () => obs.next(fileReader.result);
fileReader.onloadend = () => obs.complete();
fileReader.readAsArrayBuffer(blob);
});
}
I don't see anything obviously wrong with the response headers
HTTP/1.1 200 OK
x-amz-id-2: ...
x-amz-request-id: ...
Date: Tue, 23 Jan 2018 18:25:07 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET
Access-Control-Max-Age: 3000
Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method
Last-Modified: Thu, 18 Jan 2018 22:25:33 GMT
Server: AmazonS3
ETag: ...
Accept-Ranges: bytes
Content-Type: binary/octet-stream
Content-Length: 148341
Any insight would be helpful.

Angular 2 Token: Response for preflight has invalid HTTP status code 400

I have an Angular2/TypeScript application running i Visual Studio Code.
An API running in VS 2015. This is the API project: http://www.asp.net/web-api/overview/security/individual-accounts-in-web-api
I can use the API and create new users, but when I try to login(Use the Token function), then I get the following error:
XMLHttpRequest cannot load https://localhost:44305/Token. Response for preflight has invalid HTTP status code 400
The header looks like this:
Request URL:https://localhost:44305/Token
Request Method:OPTIONS
Status Code:400
Remote Address:[::1]:44305
Response Headers
cache-control:no-cache
content-length:34
content-type:application/json;charset=UTF-8
date:Wed, 10 Aug 2016 19:12:57 GMT
expires:-1
pragma:no-cache
server:Microsoft-IIS/10.0
status:400
x-powered-by:ASP.NET
x-sourcefiles:=?UTF-8?B?QzpcQ2hlY2tvdXRcQVBJXzJ2czJcQVBJXEFQSVxUb2tlbg==?=
Request Headers
:authority:localhost:44305
:method:OPTIONS
:path:/Token
:scheme:https
accept:*/*
accept-encoding:gzip, deflate, sdch, br
accept-language:en-US,en;q=0.8,da;q=0.6,nb;q=0.4
access-control-request-headers:authorization
access-control-request-method:POST
cache-control:no-cache
origin:http://evil.com/
pragma:no-cache
referer:http://localhost:3000/signin
user-agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36
My angular service looks like this:
loginAccount(account: Account): Observable<string> {
var obj = { Email: account.Email, Password: account.Password, grant_type: 'password' };
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions( {method: RequestMethod.Post, headers: headers });
let body = JSON.stringify(obj);
console.log('loginAccount with:' + body);
return this._http.post('https://localhost:44305/Token', body, options)
.map(this.extractData)
.catch(this.handleError);
}
When I use the AJAX funtions that a in the API project: http://www.asp.net/web-api/overview/security/individual-accounts-in-web-api then it works fine ?? What am I doing wrong in the Angular POST request ?
I found the solution. Thanks to the comments on the API site: http://www.asp.net/web-api/overview/security/individual-accounts-in-web-api
I had to set the correct header for application/x-www-form-urlencoded; charset=UTF-8 and serialize the object i posted. I canĀ“t find an Angular serializer method, so I made my own(copy from another stackoverflow site) in JavaScript.
Here is the final call when the user login on the API and request a token, when using Angular2 & TypeScript:
loginAccount(account: Account): Observable<string> {
var obj = { UserName: account.Email, Password: account.Password, grant_type: 'password' };
let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' });
let options = new RequestOptions( {method: RequestMethod.Post, headers: headers });
let body = this.serializeObj(obj);
return this._http.post('https://localhost:44305/Token', body, options)
.map(this.extractData)
.catch(this.handleError);
}
private serializeObj(obj) {
var result = [];
for (var property in obj)
result.push(encodeURIComponent(property) + "=" + encodeURIComponent(obj[property]));
return result.join("&");
}
I was also facing same issue from last week and searched on google and stack overflow but all solutions in vein. but after lot of reading and investigation we have found below solution, we were facing issue in only POST method,GET called successfully.
Instead of directly passing Options we need to first stringify option object like JSON.stringify(options)
CreateUser(user:IUser): Observable<void> {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Accept', 'application/json');
let options = new RequestOptions({ headers: headers });
return this._http.post('http://localhost:22736/api/Employee/Create', **JSON.stringify(options)**)
.map((res: Response) => {
return res.json();
})
.catch(this.handleError);
}
It worked for me, Hope it will help others too.
I found that in angular 4 you have to make it like this.
public addQuestion(data: any): Observable<Response> {
let headersObj = new Headers();
headersObj.set('Content-Type', 'application/x-www-form-urlencoded');
let requestArg: RequestOptionsArgs = { headers: headersObj, method: "POST" };
var params = new URLSearchParams();
for(let key of Object.keys(data)){
params.set(key,data[key]);
};
return this.http.post(BaseApi.endpoint + 'Question', params.toString(), requestArg)
.map((res: Response) => res.json().data);
}
Another native solution is by using HttpParams class and it's toString() method:
let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' });
let options = { headers, observe: 'response' };
const body = new HttpParams()
.set('grant_type', 'password')
.set('username', accountInfo.username)
.set('password', accountInfo.password);
return this._http.post('https://localhost:44305/Token', body.toString(), options)
toString() - Serialize the body to an encoded string, where
key-value pairs (separated by =) are separated by &s.
Note. Also it works without setting the headers