nginx read response header when multiple headers have the same name - nginx

I want to read the following response headers.
Response-Header:
...
set-cookie: somecookie=7ABFBB3446C856779B59A837DE3946F7DB; Path=/; Secure;
set-cookie: wantedcookie=12414ASDFAFADFW2342342; Path=/; Secure;
...
The variable $sent_http_set_cookie contains the first header
$sent_http_set_cookie = somecookie=7ABFBB3446C856779B59A837DE3946F7DB; Path=/; Secure;
--
How to read the second header in order to get the value of the wantedcookie?
The nginx configuration looks like this:
location /api {
add_header X-Debug "${sent_http_set_cookie}";
}

I have the same problem with you. I solved it by using the following code
local headers = ngx.resp.get_headers()
ngx.log(ngx.ERR, " set-cookie type is ", type(headers['set-cookie']))
ngx.log(ngx.ERR, "cookie headers are", require("cjson").encode(headers["set-cookie"]))
if there are multiple headers with the same, then headers[name] is a table.
ps: the code block show be placed in header_filter phase.

Related

Spring REST Controller is not responding to Angular request

I have an app to create server certificate requests, just as if one were using java keytool or something. I'm trying to return the created certificate request and the key in a zip file, but for the life of me, I can't get my REST controller to respond to the http request. CORRECTION: The controller responds, but the code within the method is never executed.
The server does receive the request, because my CORS filter is executed. But I have a debug set in the controller method, and it's never triggered. Is the signature of the method correct? I need another set of eyes, please?
Here is my controller code:
#RequestMapping(method = RequestMethod.POST, value = "/generateCert/")
public ResponseEntity<InputStreamResource> generateCert(#RequestBody CertInfo certInfo) {
System.out.println("Received request to generate CSR...");
byte[] responseBytes = commonDataService.generateCsr(certInfo);
InputStreamResource resource = new InputStreamResource(new ByteArrayInputStream(responseBytes));
System.out.println("Generated CSR with length of " + responseBytes.length);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=certificate.zip")
.contentType(MediaType.parseMediaType("application/zip"))
.contentLength(responseBytes.length)
.body(resource);
}
And here is the Angular request:
generateCertificate(reqBody: GenerateCert) {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
this.http.post(this.urlGenerateCert, JSON.stringify(reqBody), {headers: headers}).subscribe(
(data) => {
let dataType = data.type;
let binaryData = [];
binaryData.push(data);
this.certBlob = new Blob(binaryData);
});
return this.certBlob;
}
And finally, the request and response headers I copied from the Network Panel:
Response
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Content-Type, Authorization, Accept, X-Requested-With, remember-me
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Origin: *
Access-Control-Max-Age: 3600
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Length: 0
Date: Thu, 27 Dec 2018 22:48:00 GMT
Expires: 0
Location: http://localhost:8102/login
Pragma: no-cache
Set-Cookie: JSESSIONID=EDACE17328628D579670AD0FB53A6F35; Path=/; HttpOnly
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Request
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Content-Length: 205
Content-Type: application/json
Host: localhost:8102
Origin: http://localhost:4200
Referer: http://localhost:4200/generateCerts
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36
I really struggled with getting CORS working, so maybe that's interfering with the request? I hate to post all that code unless absolutely necessary. Anybody got any ideas?
Listing of request/response headers lack information on URL, method and most important response status code.
Seeing Location: http://localhost:8102/login among response headers I can guess that it could be 401 Unauthorized or anything else that redirects to the login page. Hence, if there is an auth filter in the filter chain, it may be a culprit.
The following request headers
Host: localhost:8102
Origin: http://localhost:4200
suggests that you are doing CORS and the CORS filter may be involved indeed and fulfill response before the request gets routed to the controller. I suggest setting a breakpoint into the CORS filter (and into others if any) and debug it to the point where the response is returned.
define a proxy.conf.json
{
"/login*": {
"target":"http://localhost:8080",
"secure":false,
"logLevel":"debug"
}
}
now in your package.json
"scripts": {
"start":"ng serve --proxy-config proxy.config.json"
}
I think there is issue while getting connection in both webapp.please try .
When Angular encounters this statement
this.http.post(url,body).subscribe(data => # some code
);
It comes back immediately to run rest of the code while service continues to execute. Just like Future in Java.
Here if you
return this.cert;
You will not get the value that may eventually get populated by the this.http service. Since the page has already rendered and the code executed. You can verify this by including this within and outside the Observable.
console.log(“Inside/outside observable” + new Date().toLocalTimeString());
Thanks to everyone who contributed. I discovered the error was due to the headers of my controller method. After changing them, the method was invoked properly. This is what worked:
#RequestMapping(method = RequestMethod.POST, path = "/generateCert",
produces = {MediaType.APPLICATION_OCTET_STREAM_VALUE}, consumes = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<byte[]> generateCert(#RequestBody CertInfo certInfo) {
byte[] responseBytes = commonDataService.generateCsr(certInfo);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE)
.contentLength(responseBytes.length)
.body(responseBytes);
}

How do i pick specific cookies?

How can I select specific cookies from a response?
The response I'm getting has 6 Set-Cookie rows, but I just need some of them for my next post.
HTTP/1.1 200 OK
date: Thu, 05 Mar 2015 13:49:29 GMT
cache-control: no-cache="set-cookie, set-cookie2"
expires: Thu, 01 Dec 1994 16:00:00 GMT
Set-Cookie: JSESSIONID-AUTH=0000Q77IB2vtdMjRmqnsja8ciUE:18j7lq1fl;Secure; Path=/
Set-Cookie: PD_STATEFUL_e0255922-d1d6-11e3-9144-005056bc2960=%2Fnauth2;Secure; Path=/
Set-Cookie: PD-SESSION-ID=1_4_0_Mip9xQRE1J80beniD1eh-7Le1L+X8uwfIRVUZdKvJUKO2OIB;Secure; Path=/; HttpOnly
Set-Cookie: iampsc1110=rd520o00000000000000000000ffff0a101fa3o1110;secure; path=/
Set-Cookie: TSaee27a=e4d514b3ab1503842b07e9b4d4ee0db30a6a3a54c730b09754f85edbe54ca44a641b9f7bf3fdf509ca7d6de2ed2d4e69c8c3db3f6623dd16fb85456b4ced6f5a34c171e7a460affd34c171e70025563134c171e75f534b1f34c171e7; Path=/
You're right, there is no proper way to do this yet. Here are 2 workarounds:
Manually, you can go and delete the cookies you don't want. In the Requests menu, pick Cookies then Show Cookies. Use the search box to find the cookies you'd like to get rid of.
A more complex solution, but that exactly fits your need, I think. Use a Custom dynamic value (right click on the field, and pick Extensions > Custom), instead, and use the following JavaScript code snippet:
function evaluate(context){
// Set here the cookies you'd like to return
var wantedCookies = ["datr", "reg_fb_ref"];
var regex = /^(\w+)\=([^;\s]+)/g;
// Request
// Uses here the current request, you can use getRequestByName("name of the request") instead
var request = context.getCurrentRequest();
// Get response cookies
var cookies = request.getLastExchange().getResponseHeaderByName("Set-Cookie").split(", ");
var filteredCookies = [];
for (var i in cookies) {
var cookie = cookies[i];
var match = regex.exec(cookie);
if (match && wantedCookies.indexOf(match[1]) >= 0) {
filteredCookies.push(match[0]);
}
}
return filteredCookies.join(",");
};
That basically parses manually the response cookies, and returns the ones you need.

Log in value from Set-Cookie header in nginx

Is it possible to write in nginx access log value of key 'uuid' from Cookie for server response (header: Set-Cookie)?
$cookie_uuid - return uuid that sent client
$sent_http_set_cookie - return whole header Set-Cookie: 'uuid=897587e7-a733-422f-9daa-b3105a5895aa; domain=domain.com; path=/; expires=Tue, 09-Aug-2033 01:17:54 GMT', but I need save only value for key 'uuid'
Thanks
map $sent_http_set_cookie $resp_uuid {
~*uuid=(?<u>[0-9a-f-]+) $u;
}
Reference:
http://nginx.org/r/map
man pcresyntax

SignalR routing issue, get 200 ok but response empty

I have an existing MVC application which I am integrating a hub into, now I have setup the hub like so:
routeTable.MapHubs("myapp/chat/room", new HubConfiguration { EnableCrossDomain = true, EnableDetailedErrors = true, EnableJavaScriptProxies = true });
Then in the clientside I am connecting like so:
var connection = $.hubConnection(SystemConfiguration.ServiceUrl + "/myapp/chat/room", { useDefaultPath: false });
var hub = this.Connection.createHubProxy("ChatHub"); // Same name as on the hub attribute
connection.start().done(function(){ /* do stuff */});
Then I see the HTTP Request like so:
http://localhost:23456/myapp/chat/room/negotiate?_=1374187915970
Response Headers
Access-Control-Allow-Cred... true, true
Access-Control-Allow-Head... content-type, x-requested-with, *
Access-Control-Allow-Meth... GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Orig... http://localhost:34567, http://localhost:34567
Access-Control-Max-Age 10000
Cache-Control no-cache
Content-Length 420
Content-Type application/json; charset=UTF-8
Date Thu, 18 Jul 2013 22:52:18 GMT
Expires -1
Pragma no-cache
Server Microsoft-IIS/8.0
X-AspNet-Version 4.0.30319
X-Content-Type-Options nosniff
Request Headers
Accept application/json, text/javascript, */*; q=0.01
Accept-Encoding gzip, deflate
Accept-Language en-US,en;q=0.5
Content-Type application/x-www-form-urlencoded; charset=UTF-8
Host localhost:23456
Origin http://localhost:34567
Referer http://localhost:34567/myapp/chat?chatId=1764a2e3-ff6f-4a17-9c5f-d99642301dbf
User-Agent Mozilla/5.0 (Windows NT 6.2; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0
The response though contains no body, its got a 200 status though... I am debugging on the server and the hub methods are never hit. The only non standard thing in this scenario is that I have a custom CORS HttpModule which intercepts traffic and appends the CORS required headers, as you can see in the response, so not sure if this confuses SignalR's CORS support in some way. Anyway I can see the HttpModule being hit so it goes past there fine, but is somehow lost between there and the hub.
Tried googling but not much info on this topic...
The issue seems to be down to my CORS handling at HttpModule level, it must somehow conflict with SignalR... if I put a check in the module to see if the URL contains "chat/room" and just ignore the request if needed it then works fine, however it feels like a hack, but at least it works now.

How can I remove 'no-cache="Set-Cookie"' when I add a cookie to a HttpResponse?

I'm currently returning a cookie from a web service with code like this:
HttpResponse response = ...;
var cookie = new HttpCookie(cookieName)
{
Value = cookieValue,
Expires = expiresDate,
HttpOnly = true,
Path = "/",
Secure = true,
};
response.Cookies.Add(cookie);
This results in the automatic addition of a no-cache directive in my Cache-Control header:
Cache-Control: public, no-cache="Set-Cookie", must-revalidate, max-age=60
My client happens to handle this directive by straight up not caching the response at all. If I manually remove the no-cache directive before it hits the client, caching works great.
How can I prevent .NET from automatically adding this directive to responses containing cookies?
HttpResponse determines whether it should add this directive based on whether the Cookies collection is non-empty. Therefore, if you add the header manually you can hide its presence from .NET:
response.AddHeader("Set-Cookie", String.Format(
"{0}={1}; expires={2}; path=/; secure; HttpOnly",
cookieName, cookieValue, expiresDate.ToString("R")));

Resources