HOWTO override Axis2 request headers for .NET web service? - asp.net

I have to use a 3rd party web service implemented in .NET 2.0 (on IIS, of course).
I have to make a java client. I am using wsdl2java to generate the SOAP stub.
As the original Apache Axis project now appears unmaintained, and I was having some problems parsing some responses from the service, I converted the client to use the latest (1.5) version of Axis2. Now, the .NET service won't even recognize my requests.
I managed to get the "chunking" turned off (where "stub" is a variable of type MumbleStub generated by wsdl2java, and I am showing what are several lines of code as one horrific line here):
stub._getServiceClient().getOptions().setProperty( HTTPConstants.CHUNKED, Boolean.FALSE);
.. so at least the service recognizes my request AS a request, albeit a bad one: "HTTP/1.1 400 Bad Request" is the response now (as opposed to an "intro / summary" page offering me a link to the WSDL).
I noticed that the Axis ("1") request had a different Content-TYpe header (text/xml, vs application/soap-xml), and I am wondering how to change this request header, if that is in fact the problem.
Alternately, has anybody else had this problem? Is the problem really the (undisplayable here, as it looks like "element injection" to the blog engine) ... xml version-"1.0" ... "XML meta intro tag" that Axis2 added to the beginning of the request?
WS-Deathstar, indeed.

As you mention the different content-type header I guess your client tries to send SOAP 1.2 requests and the 3rd party app only understands SOAP 1.1
Try changing the used soap version as AFAIK AXIS2 uses SOAP 1.2 by default
stub._getServiceClient().getOptions().setSoapVersionURI(org.apache.axiom.soap.SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI);

Related

ASP.NET core: HTTP HEAD requests and Content-Length header

This question is related to an ASP.NET core 2.2 web application (targeting .NET core) exposing some web api controllers implemented used the mvc middleware.
All the action methods available in all the controllers must respond to both the GET and the HEAD http methods.
We noticed that ASP.NET core automatically add the Transfer-Encoding header with the value chunked and, according to the specifications, omits the Content-Length header (see this MDN page for more details).
According to this github issue on the ASP.NET core repository it seems that this behaviour depends on a precise design decision of the Kestrel web server, so this is the intended behaviour.
That said, each time we issue an HEAD request to any route of our application we get a response having the Content-Length header set to 0, even when the corresponding GET request (I mean a GET request having the same path) returns a non empty response body.
According to what I read on various sources, it seems that the Content-Length header is not mandatory for the response to an HEAD request, but when included it should have the same value as the corresponding GET request. So the value 0 that we see on each HEAD request does not seem correct to me.
Is it a side effect of the fact that, for the corresponding GET request, ASP.NET core sends the response by using chunks (as explained above Transfer-Encoding is always chunked for GET requests) ?
Another doubt is related to any kind of cache issuing HEAD requests to our application in order to decide whether or not to purge a cached response: does the zero-valued Content-Length pose a risk for the correctness of caching behaviour ?
EDIT OF 27th MARCH 2018
We repeated our tests and we got different but more meaningful results. I can confirm that both the GET and HEAD requests do not send any Content-Length header. This definitely makes sense according to the fact that the response body is always transmissed by chunks to the client as explained above.
That said I think that the ASP.NET core behaviour definitely makes sense to me.

IIS 8.5 400 Bad Request

I've some difficulties with an ASP.Net Core Web Api Application which is hosted on an IIS 8.5.
The IIS 8.5 returns a 400 status code for a specific post request.
The faulty request is executed by an web application which is hosted on the same domain with a different port. The API is configured to handle cors and the preflight of the faulty request is successfully completed.
I noticed a weird thing:
The Api is deployed with Swagger UI included. So I tried to reproduce the error with the Swagger UI. But in this case the request is successful.
The body and the url of both requests are absolutely the same and there are no noticeable differences in the headers except, of course, of the request origin.
It looks like the request is not processed by the Api at all (I should see sth. in our log files in this case), so I'm pretty sure the error occurs somewhere in the IIS itself.
I've already investigated the httperr.log file. It contains the flowing line at the time of the failed request:
2018-12-05 15:38:36 192.168.100.132 62121 192.168.100.173 1142
HTTP/1.1 POST /api/some/request/path 400 13 BadRequest myServicePool
I was hoping this file would contain more details about the cause of the error.
I was wondering if the "13" before "BadRequest" has any special meaning?
Does anyone have an idea, based on the information given, why this error occurs? I don't really think so. But I would be more than happy if anybody can give me a hint where to search for more details about the cause of the error.
Let me know if you need more details.
It's better if we can have sample code of how you are sending the request in your code.
However, with the given facts I assume the problem is in the content of the request body. Even the swagger request and the request you are sending look like exactly the same, it should be varying in some aspects.
Are you using a JSON converter? If you are using a JSON converter and if you are serializing a .NET model to a JSON string and attaching in the request please make sure that you are formatting it with Camel Case.
Because by default it might just be converting the .NET model as it is with the Pascal case.
EXAMPLE
I'll elaborate this using Newtonsoft JSON library.
.NET model serialized without specifying the format
var businessLeadJson = JsonConvert.SerializeObject(ObjectA);
Converted result - {"Company":"sample","ContactName":"contact 1"}
.NET model serialized by specifying the format
var businessLeadJson = JsonConvert.SerializeObject(businessLead, new
JsonSerializerSettings() { ContractResolver = new CamelCasePropertyNamesContractResolver() });
Converted result - {"company":"sample","contactName":"contact 1"}
Please notice the case of the property names in JSON strings. The first letter is capital in the first result.
Therefore I recommend you to try serializing your objects that are attaching as the payload (request body) by specifying the formatting, becasue REST APIs expect the JSON strings in the correct format.
Please specify the Camel case formatting when you are serializing the object of your request body.
Good Luck..!
I've justed managed to reproduce this error by accident.
The problem is, that the application send an empty Authorization-Header if the user hasn't login yet.
It seems that causes an Bad Request on some configurations/IIS versions, or what ever the difference is between the systems,and on some it's no problem.

ASP.NET Web API: Change Request Headers

A JavaScript client that I have no control over is sending the incorrect HTTP request headers to my Web API services. More specifically, it's using a library that is sending an incorrect OData header.
Is there any way that I can intercept the HTTP request before it hits my services? Can I add/remove/update headers or query string info?
For instance, if I receive the following HTTP header:
GET /Some/API HTTP/1.1
Host: myhost.com:80
MaxDataServiceVersion: 2.0
I'd like to know how to modify it to the following before the OData libraries take over:
GET /Some/API HTTP/1.1
Host: myhost.com:80
MaxDataServiceVersion: 4.0
The header isn't incorrect. Your client expects an OData v2 service and even if you did manipulate the headers, it probably won't be able to understand the response from your server.
But you could use a simple HTTP proxy to rewrite the headers if you really want to try that route.
If you do that, make sure your OData server supports the Atom format because the OData JSON format changed completely between versions 2 and 4, so there's no way that JavaScript client will understand it. The Atom format changed as well, but if the client's parser is extremely lenient, it might work.

Generating HTTP Request

In how many ways can an HTTP request be generated?
There are endless ways how you can create and from where you can send HTTP requests to a server. Actually your server has no idea, what the origin of such a request is (if it's AJAX or "regular" request, or sent from a console application or ...)
But there are HTTP methods (HTTP verbs) that (can) tell the server about the intent of the request: http://en.wikipedia.org/wiki/HTTP_Verbs#Request_methods
Also you can set headers in a request, for example the content-type or the accepted encoding: http://en.wikipedia.org/wiki/List_of_HTTP_header_fields
Most JavaScript libraries for example set the (non-standard) HTTP header X-Requested-With, so your application can differentiate between regular and ajax requests.
You see, it's even possible to set your own, non-standard headers. There are endless possible combinations...
HttpRequest is a C# class that wraps a petition sent by a client during a Web request.
There are many ways to generate it. The most usual one happens when your browser connects to an ASP.NET website.
You can, for example, create your own custom HttpRequest to petition a specific web page from a C# console application.
Are you trying to achieve something more specific?

Passing params in the URL when using HTTP POST

Is it allowable to pass parameters to a web page through the URL (after the question mark) when using the POST method? I know that it works (most of the time, anyways) because my company's webapp does it often, but I don't know if it's actually supported in the standard or if I can rely on this behavior. I'm considering implementing a SOAP request handler that uses a parameter after the question mark to indicate that it is a SOAP request and not a normal HTTP request. The reason for this that the webapp is an IIS extension, so everything is accessed via the same URL (ex: example.com/myisapi.dll?command), so to get the SOAP request to be processed, I need to specify that "command" parameter. There would be one generic command for SOAP, not a specific command for each SOAP action -- those would be specified in the SOAP request itself.
Basically, I'm trying to integrate the Apache Axis2/C library into my webapp by letting the webapp handle the HTTP request and then pass off the incoming SOAP XML to Axis2 for handling if it's a SOAP request. Intuitively, I can't see any reason why this wouldn't work, since the URL you're posting to is just an arbitrary URL, as far as all the various components are concerned... it's the server that gives special meaning to the parts after the question mark.
Thanks for any help/insight you can provide.
Lets start with the simple stuff. HTTP GET request variables come from the URI. The URI is a requested resource, and so any webserver should (and apache does) have the entire URI stored in some variable available to the modules or appserver components running within the webserver.
An http POST which is different from an http GET is a separate logical call to the webserver, but it still defines a URI that should process the post. A good webserver (apache being one) will again make the URI available to whatever module or appserver is running within it, then will additionally make available the variables which were sent in the POST headers.
At the point where your application takes control from apache during a POST you should have access to both the GET and POST variables and be able to do whatever control logic you wish, including replying with a SOAP protocol instead of HTML.
If you are asking whether it is possible to send parameters via both GET and POST in a single HTTP request, then the answer is "YES". This is standard functionality that can be used reliably AFAIK.
One such example is sending authentication credentials in two pieces, one over GET and the other through POST so that any attempt to hijack a session would require hijacking both the GET and POST variables.
So in your case, you can use POST to contain the actual SOAP request but test for whether it is a SOAP request based on the parameter passed in GET (or in other words through the URL).
I believe that no standard actually defines the concept of "HTTP parameters" or "request variables". RFC 1738 defines that an URL may have a "search part", which is the substring after the question mark. HTML specifies in the form submission protocol how a browser processing a FORM element should submit it. In either case, how the server-side processes both the search part and the HTTP body is entirely up to the server - discarding both would be conforming to these two specs (but fairly useless).
In order to determine whether you can post a search part to a specific service, you need to study this service's protocol specification. If the service is practically defined by means of a HTML form, then you cannot use a mix - you can't even use POST if the FORM specifies GET (and vice versa). If you post to a web service, you need to look at the web service's WSDL - which will typically mandate POST; with all data in a SOAP message. Etc.
Specific web frameworks may have the notion of "request variables" - whether they will draw these variables both from a search part and a request body, you need to find out in the product documentation.
I deployed a web application with 3 (a mobile network operator) in the UK. It originally used POST parameters, but the 3 gateway stripped them (and X-headers as well!). So beware...
allowable? sure, it's doable, but i'm leaning towards the spec suggesting dual methods isn't necessarily supposed to happen, or be supported. RFC2616 defines HTTP/1.1, and i would argue suggests only one method per request. if you think about your typical HTTP transaction from the client side, you can see the limitation as well:
$ telnet localhost 80
POST /page.html?id=5 HTTP/1.1
host: localhost
as you can see, you can only use one method (POST/GET, etc...), however due to the nature of how various languages operate, they may pick up the query string, and assign it to the GET variable. ultimately though, this is a POST request, and not a GET.
so basically, yes this functionality exists, is it intended? i would say no.

Resources