ASP.NET Core Azure App Service httpContext.Request.Headers["Host"] Value - asp.net

Faced strange behaviour today.
We are hosting asp.net core 1.1 web app with Azure App Services and using subdomains that route to a specific controller or area.
So in my SubdomainConstraint: IRouteConstraint I use
HttpContext.Request.Headers["Host"]
to get host name. That previously returned smth like that
mywebsite.com or subdomain.mywebsite.com
Starting today (or a maybe yesterday) it started to return my App Service name instead of host name. On localhost everything works fine.
Enumerating through
Context.Request.Headers
in one of my Views gives me on localhost:
Accept :
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding : gzip, deflate, sdch, br
Accept-Language : ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4,ca;q=0.2
Cookie : .AspNetCore.Antiforgery....
Host : localhost:37202
User-Agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36
Upgrade-Insecure-Requests : 1
in Azure App Service:
Connection : Keep-Alive
Accept : text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding : gzip, deflate, sdch
Accept-Language : ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4,ca;q=0.2
Cookie : AspNetCore.Antiforgery....
Host : mydeploymentname:80
Max-Forwards : 10
User-Agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36
Upgrade-Insecure-Requests : 1
X-LiveUpgrade : 1
X-WAWS-Unencoded-URL : /
X-Original-URL : /
X-ARR-LOG-ID : 9c76e796-84a8-4335-919c-9ca4rb745f4fefdfde
DISGUISED-HOST : mywebsite.com
X-SITE-DEPLOYMENT-ID : mydeploymentname
WAS-DEFAULT-HOSTNAME : mydeploymentname.azurewebsites.net
X-Forwarded-For : IP:56548
MS-ASPNETCORE-TOKEN : a97b93ba-6106-4301-87b2-8af9a929d7dc
X-Original-For : 127.0.0.1:55602
X-Original-Proto : http
I can get what I need from
Headers["DISGUISED-HOST"]
But having problems with redirects to a login page, it redirects to the wrong URL with my deployment name.
Wondering if I could mess something up anywhere. But we've made last deployment like a few days ago and it worked fine after that.

This is caused by a regression in AspNetCoreModule deployed to a small number of apps in Azure App Service. This issue is being investigated. Please follow this thread for status.
Here is a workaround you can use until the fix is deployed: in your Configure method (typically in startup.cs), add the following:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.Use((ctx, next) =>
{
string disguisedHost = ctx.Request.Headers["DISGUISED-HOST"];
if (!String.IsNullOrWhiteSpace(disguisedHost))
{
ctx.Request.Host = new Microsoft.AspNetCore.Http.HostString(disguisedHost);
}
return next();
});
// Rest of your code here...
}

Related

wordpress json API fetch problem from localhost

if I call the json api v2 in wordpress from a local website via fetch, it works without any problems.
fetch('https://example.com/wp-json/wp/v2/pages/', { method: 'GET', headers: { 'content-type': 'application/json' } } )
when I call the old json api via fetch I get an error unable to fetch (directly with the browser no problem)
fetch('https://example.com/?json=get_page_index&custom_fields=*&dev=1&count=800', { method: 'GET', headers: { 'content-type': 'plain/text' } } )
in the network debug tab I see
provisional headers are shown Learn more
application/json: application/json
DNT: 1
Referrer: http://localhost:8080/
User-Agent: Mozilla/5.0 (iPad; CPU OS 13_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/87.0.4280.7
What could be the reason.

.Net Core Cross Site Cookie Not Being Set by Chrome or Firefox

I am trying to use a cookie sent from an Asp.Net Core web api site in a cross-site configuratioun. I can see the cookie arrive in the Response, but from what I can tell, it's not being set by either Firefox or Chrome. Either way, it's not being sent back on subsequent requests to the API. When I use Postman, everything works great.
I've tried using .Net Core middleware for authentication cookies with server and app configuration in Startup.cs. But I get the same result if I use the direct approach of appending the cookie to the HTTP response in my controller (shown in the sample code below).
My web site is running out of VS Code from a minimal create-react-app, npm start, localhost port 3000.
My API is running of out Visual Studio 2019, .Net Core 3.1, web api site, port 44302. I've also tried deploying to an Azure app service so that my localhost web site could call a non-localhost API. Cookie still not set or sent.
Question is, how do I get the browser to set and then send the cookie back to the API when developing in localhost (or deployed anywhere, for that matter!)? I've spent hours combing Stack Overflow and other docs for the answer. Nothing has worked. Thanks much for any help!
From Startup.cs. Define CORS policy. Note the allow credentials that pairs with the web site's xhr withCredentials:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddCors(options =>
{
options.AddDefaultPolicy(
builder =>
{
builder
.SetIsOriginAllowed(host => true)
.AllowCredentials()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
...
}
From my controller endpoint simulating login:
[HttpPost]
public IActionResult FauxLogin(string Email, string Pwd)
{
Response.Cookies.Append("LoginCookie", "123456", new CookieOptions
{
//Domain = ".app.localhost", // some suggest specifying, some suggest leaving empty for default.
Path = "/",
Secure = true,
HttpOnly = false,
SameSite = SameSiteMode.None
});
return Ok(new { success = true });
}
Javascript function calling back to the API:
function callApi() {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://localhost:44302/api/account/echo', true);
xhr.withCredentials = true;
xhr.send(null);
}
Response header from dev tools for faux login call. Set Cookie present:
content-type: application/json; charset=utf-8
server: Microsoft-IIS/10.0
set-cookie: LoginCookie=123456; path=/; secure; samesite=none
access-control-allow-origin: http://localhost:3000
access-control-allow-credentials: true
x-powered-by: ASP.NET
date: Sun, 31 Oct 2021 23:27:22 GMT
X-Firefox-Spdy: h2
Request header calling back to API. No cookie.
GET /api/account/echo HTTP/2
Host: localhost:44302
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Origin: http://localhost:3000
Connection: keep-alive
Referer: http://localhost:3000/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site

Why won't Splash render this webpage?

I'm quite new to Splash and tho I was able to get Splash setup on my Ubuntu 18 (via Splash/Docker) it gives me different results for this page:
https://www.overstock.com/Home-Garden/Area-Rugs/31446/subcat.html
Normally it's rendered like so:
But when I try to render it in Splash, it renders it like this:
I have tried changing the user agent in Splash to this:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36
Consequently, this makes the Splash script like so:
function main(splash, args)
splash:set_user_agent(
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36'
)
assert(splash:go(args.url))
assert(splash:wait(0.5))
return {
html = splash:html(),
png = splash:png(),
har = splash:har(),
}
end
Yet, despite these additions, it still fails to render the page.
How can I get Splash to render this page?
It seems like overstock.com requires a Connection and Accept headers. Add it to your request and it should work as expected.
Tested on Postman, with and without the Connection: keep-alive && Accept: */* headers; I get the same error page:
After adding the two headers above:
Therefor your request should be edited accordingly:
function main(splash, args)
splash:set_custom_headers({
["Connection"] = "keep-alive",
["Accept"] = "*/*",
})
assert(splash:go(args.url))
assert(splash:wait(0.5))
return {
html = splash:html(),
png = splash:png(),
har = splash:har(),
}
end

How http request with "Sec-Fetch-Mode: no-cors" in Blazor Webassembly

How is it possible to make a request by HttpClient with the HTTP request header Sec-Fetch-Mode: no-cors in Blazor Webassembly?
My actuel code is :
var hc = new HttpClient();
var responseHTTP = await hc.GetAsync("https://www.somedomain.com/api/");
But this produces the following HTTP request headers :
:authority: www.somedomain.com
:method: GET
:path: /api/json?input=test&key=AIzaSyDqWvsxxxxxxxxxxxxxxxxx1R7x2qoSkc&sessiontoken=136db14b-88bd-4730-a0b2-9b6c1861d9c7
:scheme: https
accept: */*
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9
origin: http://localhost:5000
referer: http://localhost:5000/places
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: cross-site
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36
x-client-data: CJS2yQxxxxxxxxxxxxxxxxxxxxxxxxygEI7bXKAQiOusoBCObGygE=
To specifically answer your question, you need to create a HttpRequestMessage first.
e.g.
var request = new HttpRequestMessage(HttpMethod.Get, "https://www.somedomain.com/api/");
request.SetBrowserRequestMode(BrowserRequestMode.NoCors);
request.SetBrowserRequestCache(BrowserRequestCache.NoStore); //optional
using (var httpClient = new HttpClient())
{
var response = await httpClient.SendAsync(request);
var content = await response.Content.ReadAsStringAsync();
}
This will correctly set the sec-fetch-mode header to no-cors
I've found however, that the response comes back as empty even though upon inspection in fiddler the response is there.
The closest I got to understanding the problem is through this issue here but unfortunately the bug was closed.

POST raw to server Processing

I have an Intel Edison running a Node.JS server that is printing everything I post to it into the console. I can successfully post to it using Postman and see the sent raw data in the console.
Now I'm using Processing to POST to it, which will fire off different events on the Node.JS server.
My problem is that I can't seem to successfully POST the raw body to the server, I've been trying to get this working for several hours already.
import processing.net.*;
String url = "192.168.0.107:3000";
Client myClient;
void setup(){
myClient = new Client(this, "192.168.0.107", 3000);
myClient.write("POST / HTTP/1.1\n");
myClient.write("Cache-Control: no-cache\n");
myClient.write("Content-Type: text/plain\n");
//Attempting to write the raw post body
myClient.write("test");
//2 newlines tells the server that we're done sending
myClient.write("\n\n");
}
The console shows that the server received the POST, and the correct headers, but it doesn't show any data in it.
How do I specify the that "test" is the raw POST data?
The HTTP code from Postman:
POST HTTP/1.1
Host: 192.168.0.107:3000
Content-Type: text/plain
Cache-Control: no-cache
Postman-Token: 6cab79ad-b43b-b4d3-963f-fad11523ec0b
test
The server output from a POST from Postman:
{ host: '192.168.0.107:3000',
connection: 'keep-alive',
'content-length': '4',
'cache-control': 'no-cache',
origin: 'chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop',
'content-type': 'text/plain',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36',
'postman-token': 'd17676a6-98f4-917c-955c-7d8ef01bb024',
accept: '*/*',
'accept-encoding': 'gzip, deflate',
'accept-language': 'en-US,en;q=0.8' }
test
The server output from my POST from Processing:
{ host: '192.168.0.107:3000',
'cache-control': 'no-cache',
'content-type': 'text/plain' }
{}
I just figured out what was wrong, I needed to add the content-length header to tell the server how much data to listen for, and then a newline before the data.
Final code:
import processing.net.*;
String url = "192.168.0.107:3000";
Client myClient;
void setup(){
myClient = new Client(this, "192.168.0.107", 3000);
myClient.write("POST / HTTP/1.1\n");
myClient.write("Cache-Control: no-cache\n");
myClient.write("Content-Type: text/plain\n");
myClient.write("content-length: 4\n");
myClient.write("\n");
myClient.write("test");
myClient.write("\n\n");
}

Resources