Expect Continue Inconsistencies on Different Environments - c#

I have some troubles with the header Expect 100-Continue on a DELETE method inside a .NET 4.5 application. The client in provides also a small content body inside the call.
The official microsoft documentation seems to imply that this header is passed by default only in PUT and POST calls with a non-empty content, but it does not say nothing about DELETE. Does anyone know if this configuration also applies to DELETE?
I'm experiencing different behaviour on different environment of my web application in particular I have some environments in which the header is never passed (even in PUT and POST) without any clue about it being deactivated.
In order to interact with this option I know only four ways:
Via ServicePointManager through
System.Net.ServicePointManager.Expect100Continue = false;
Editing client options
var c = new HttpClient();
c.DefaultRequestHeaders.ExpectContinue = false;
Adding or removing it manually on HttpWebRequest with AddHeader/Remove
Using the following property on Web.Config
<system.net>
<settings>
<servicePointManager expect100Continue="false"/>
</settings>
</system.net>
Unfortunately none of these seems to be my case. Are there any other ways to mess with this option?

Just managed to find out the solution for this issue. I found out that some of my environment use the couchbase client to handle distributed cache, differently from IIS couchbase internally sets Expect100Continue to true but it does that in the following way.
namespace Couchbase.Configuration.Client
{
public class ClientConfiguration {
//...
public ClientConfiguration()
{
//...
this.Expect100Continue = false;
}
//--
public bool Expect100Continue
{
get
{
return ServicePointManager.Expect100Continue;
}
set
{
ServicePointManager.Expect100Continue = value;
}
}
}
}
they use change this property using the static ServicePointManager method and this means that every following instantiated client will change their behaviour.
My version of Couchbase Client is 2.1.4.0

Related

Enable CORS from a specific origin on Topshelf hosted service

I'm sure this is a duplicate but none of the answers I've found appears to be working.
I have a web.api hosted as a windows service and I need to allow CORS to two specific origins.
I have this in my startup.cs
config.EnableCors(
new EnableCorsAttribute("http://customer.mydomain.com,
http://admin.mydomain.com", "*", "*")
);
var policy = new CorsPolicy()
{
AllowAnyHeader = true,
AllowAnyMethod = true,
SupportsCredentials = true
};
policy.Origins.Add("*http://customer.mydomain.com");
policy.Origins.Add("*http://admin.mydomain.com");
app.UseCors(new CorsOptions
{
PolicyProvider = new CorsPolicyProvider
{
PolicyResolver = context => Task.FromResult(policy)
}
});
So my understanding here is that I'll only allow access to my service from admin and customer subdomains?
and then on top of my controller I have
[EnableCors("*.mydomain.com","*","*")]
public class MasterDataController
everything builds and is happy but when I run my service and call a method in the controller directly from the browser URL it responds fine, shouldn't it be blocking me as I'm not calling it from mydomain.com ?
I've seen answers saying I need to send my origin in my call but surely that's not the answer as I specifically want to stop calls unless they are from my allowed origins? I feel like I'm going in circles here
[Update]
I've also added
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*.bizcash.co.za" />
</customHeaders>
to my IIS proxy and if I check the response headers when I call the method directly I see the following
*.redacted obviously being my domain. However, I can still call it directly from my browser and it shouldn't allow that should it? It should only allow the calls if made from my domain?
okay, so two problems with the question.
adding specific CORS origins doesn't stop you calling the service directly in the browser, it stops other web applications calling it. So I was testing it wrong.
So you need to make your changes, deploy it to your server and then test it via your normal applications.
to make it work this is what I have in the end
var policy = new CorsPolicy()
{
AllowAnyHeader = true,
AllowAnyMethod = true
};
policy.Origins.Add("https://customer.mydomain.com");
policy.Origins.Add("https://admin.mydomain.com");
app.UseCors(new CorsOptions
{
PolicyProvider = new CorsPolicyProvider
{
PolicyResolver = context => Task.FromResult(policy)
}
});
That's it, just that in the startup.cs and it works. Hopefully I save someone else two wasted days of life

Is there a way to use the 'AllowAnyOrigin' property on a CorsPolicy within .NET Core?

I'm currently working on integrated Cors within a .Net Core app. I have previously dealt with Cors within the full .NET Framework (4.6.1) which had the ability to set the AllowAnyOrigin property within a given CorsPolicy.
Like mentioned before, I have written a .NET Core WebApi, which I am trying to implement Cors into. I have it reading from an AppSetting stored in my appSettings.json, from which it can be either three things:
If the appsetting is set to an asterisk, then I would like to see the AllowAnyOrigin property like I have done in the full .NET framework. (This is where my problem lies.)
If the appsetting is set to a comma seperated string, such as https://example.com, https://test.com, then this is applied onto the policy as needed.
If the appsetting has been commented out or left as empty, then I am reading a list of rows from Azure Table Storage to supply a list of given origins.
Below is an example of the full .NET framework that I have dealt with before.
var origins = ConfigurationManager.AppSettings[KeyCorsAllowOrigin];
switch (origins)
{
case null:
_corsPolicy.Origins.Clear();
foreach (var item in new StorageConfigurationManager().GetRowKeys())
{
_corsPolicy.Origins.Add("https://" + item);
}
break;
case "*":
_corsPolicy.AllowAnyOrigin = true;
break;
default:
_corsPolicy.AllowAnyOrigin = false;
if (!string.IsNullOrWhiteSpace(origins)) AddCommaSeparatedValuesToCollection(origins, _corsPolicy.Origins);
break;
}
I thought that I could replicate this functionality within .NET Core and the Microsoft.AspNetCore.Cors.Infrastructure package, but it seems that Microsoft has restricted access to setting the property, and can only be read from.
Does anyone know of any way to set this?
I know you can build the CorsPolicy within the pipeline, which then uses the .AllowAnyOrigin(), but I am currently using custom Cors middleware to help with my custom policy.
There is a great article called Enabling CORS in ASP.NET Core I'll sum the interesting part for you:
to only allow GET methods on your resource, you can use the WithMethods method when you define the CORS policy:
services.AddCors(options =>
{
options.AddPolicy("AllowOrigin",
builder => builder.WithOrigins("http://localhost:55294")
.WithMethods("GET"));
});
If you need to allow any origin to access the resource, you will use AllowAnyOrigin instead of WithOrigins:
services.AddCors(options =>
{
options.AddPolicy("AllowOrigin",
builder => builder.AllowAnyOrigin());
});
Just as an answer to all this, and so that perhaps someone can be helped by this question. I looked at the source code for the AllowAnyOrigin method within the CorsPolicyBuilder class and saw how this was handled. I nearly had the solution, just forgot to clear the Origins list beforehand.
_policy.Origins.Clear();
_policy.Origins.Add(CorsConstants.AnyOrigin);

RestSharp portable RestClient Proxy property is not working

Here is what is the issue. I'm using portable RestSharp which uses HttpClient under the hood. But for iOS there is problem with HttpClient, because the Default IWebProxy instance doesn't allow to monitor requests using request monitoring software like Charles (look here to see the issue and the solution )
The solution for this is using CFNetwork.GetDefaultProxy () which returns IWebProxy and set it as proxy of a request. I tried setting the Proxy property of RestClient but it didn't work, when digging in the open source code of portable RestClient I found out that the Proxy property is not used anywhere. The only place where it is used is commented out. That method is called ConfigureProxy line 572 in RestSharp.Portable project RestClient file, and this method is called only from ConfigureHttp method line 541 same file, which is also commented out. I believe this is a bug. May be someone has forgotten to set Proxy after commenting out this code. So can someone tell me wether it will be safe to remove the commented line, or may be say the right place where to set the proxy of IHttp interface? For instance is it safe to set the proxy on the line 393 (this is again in the RestClient file) of the attached image, like
httpRequest.Proxy = this.Proxy;
strong text
I fixed this issue by myself after 2 days of debugging RestSharp.Portable 3.1.0 source code.
There is a bug in
RestSharp.Portable.HttpClient.Shared - project
DefaultHttpClientFactory - class
CreateMessageHandler - method
Original code is:
if (handler.SupportsProxy && _proxyProperty != null && proxy != null)
{
_proxyProperty.SetValue(handler, new RequestProxyWrapper(proxy), null);
}
Code does not work because _proxyProperty is null. This field initializes within constructor by reflection.
_proxyProperty = typeof(HttpClientHandler).GetProperty("Proxy");
Simulator initializes this property well, but real iOS device doesn't. I do not know why it happens.
So, here is the code that contains the fix:
if (handler.SupportsProxy && proxy != null)
{
handler.Proxy = new RequestProxyWrapper(proxy);
}
I have added this fix into my application using reflection. If you want to do the same you should wrap your authenticator(s) or implement dummy one and override two methods:
public override bool CanPreAuthenticate(IHttpClient client, IHttpRequestMessage request, ICredentials credentials)
{
return true;
}
and
public override async Task PreAuthenticate(IHttpClient client, IHttpRequestMessage request, ICredentials credentials)
{
...
// get private "handler" field of type DefaultHttpClient from client by reflection here
// get private "proxy" field of type IWebProxy from "handler" by reflection here
// set private "proxy" field if it's null by reflection here
...
}
Hope this help. Do not forget to test your solution on each platform:)
I have added new issue on github FubarDevelopment/restsharp.portable

How do I associate some custom data with current HttpRequest?

I need to somehow attach my custom data to the HttpRequest being handled by my IIS custom modules - so that code that runs in earlier stages of IIS pipeline attaches an object and code that runs in later stages can retrieve the object and use it and no other functionality of IIS pipeline processing is altered by adding that object.
The data needs to persist within one HTTP request only - I don't need it to be stored between requests. I need it to be "reset" for each new request automatically - so that when a new request comes it doesn't contain objects my code attached to the previous request.
Looks like HttpContext.Items is the way to go, although MSDN description of its purpose is not very clear.
Is using HttpContext.Current.Items the way to solve my problem?
This should work - I have done this in a project before.
I have a class which has a static property like this -
public class AppManager
{
public static RequestObject RequestObject
{
get
{
if (HttpContext.Current.Items["RequestObject"] == null)
{
HttpContext.Current.Items["RequestObject"] = new RequestObject();
}
return (RequestObject)HttpContext.Current.Items["RequestObject"];
}
set { HttpContext.Current.Items["RequestObject"] = value; }
}
}
And then RequestObject contains all my custom data so then in my app I can do
AppManager.RequestObject.CustomProperty
So far I have not come across any issues in the way HttpContext.Items works.

dynamic binding of web service URI

I have a list of servers, all exposing the same web service interface, that I need to call from my code.
i.e.
https://server1/service.asmx
https://server2/service.asmx
https://server3/service.asmx
My code needs to get this list of servers and invoke the same function on all of them.
I added a web references to this service, and I use "Dynamic" URL behavior. This is supposed to let me create an instance of the server proxy object, set the URI property at runtime, and then invoke the web methods, right?
But it seems the code generated by VS assumes the URI will come from the application's config file, which isn't the case for this app.
public SharpEyeWebService() {
this.Url = global::Company.DotNet.MyProject.Properties.Settings.Default.MyWebService;
if ((this.IsLocalFileSystemWebService(this.Url) == true)) {
this.UseDefaultCredentials = true;
this.useDefaultCredentialsSetExplicitly = false;
}
else {
this.useDefaultCredentialsSetExplicitly = true;
}
}
Is it safe to ignore the default URL the constructor uses and employ the approach I described above?
You can always set the Url, so yes this is safe. The "dynamic" you describe only influences the default Url: whether it hard-coded or comes from config.
So indeed, this is moot if you are supplying this yourself.
The awkward bit here is that it also sets UseDefaultCredentials based on what it finds - so it would be worth setting this manually so you know the value.

Categories

Resources