I'm currently working with a number of third parties, sending them data via an HttpPost with an encrypted url string. Each of the third parties sends back an xml string which I then read and use. All is good!
The question I have is this. If I send a request to a third party, and they do not provide a response, what happens? To clarify, I mean that a response string isn't returned in all cases - not just errors and timeouts.
Few things can happen:
A response is sent by the third party: It consists of the desired output (an XML string in your case.
A response is sent, but the content is 0 length: Take it into mind that HTTP response consists of two parts: HTTP headers, and content. In this case third party sends only the headers. You can consider this as String.Empty output.
A response is not sent: Third part should have sent a response according to the HTTP protocol, but they don't. Third party may close the socket or just timeout. That can happen because of an internal problem, or they are just choosing not to respond to you. This will normally result in an exception. What the exception is, though, depends on the methods/library you use to send HTTP requests.
The HTTP protocol does not include a way to not send a response. A response is always sent. It might be zero length, though.
I mean that a response string isn't returned in all cases
Is this a question or an assertion? This statement is false.
and they do not provide a response, what happens?
So what happens in case of a zero-length response? That depends entirely on your code. Neither protocol not framework care about this case.
Couldn't the socket actually be closed before any headers are sent back? Or, if the server is down?
That's a protocol violation. That's not HTTP, then. In such a situation the app is generally notified through an exception.
Related
For example, ExceptionHandlerMiddleware Middleware code on Github
uses this as:
if (context.Response.HasStarted ||...)
I don't quite get it, how can the web server starts to send response to clients when the request still in the pipeline assuming the ExceptionHandlerMiddleware is the first middleware in the pipeline? Because the request hasn't got out of ExceptionHandlerMiddleware, so it hasn't arrived to the web server, then how could it be that the web server already starts to send responses to client in this scenario?
Any middleware or handler may choose to call WriteAsync (or other similar methods) on the HttpResponse, possibly multiple times.
It's not necessarily possible for all of those writes to just be stored in local buffers, and indeed may not be desirable to just buffer locally. So, sooner or later, those Write calls are going to result in real data being sent over the network.
And, in this concrete example, a handler may have made multiple calls such as the above before it encounters an error condition that causes control to be returned to the ExceptionHandlerMiddleware.
Your specific ExceptionHandlerMiddleware example uses Microsoft.AspNetCore.Http.HttpResponse.HasStarted:
Gets a value indicating whether response headers have been sent to the client.
https://learn.microsoft.com/en-US/dotnet/api/microsoft.aspnetcore.http.httpresponse.hasstarted?view=aspnetcore-5.0
There is also Microsoft.Net.Http.Server.Response.HasStarted:
Indicates if the response status, reason, and headers are prepared to send and can no longer be modified. This is caused by the first write or flush to the response body.
https://learn.microsoft.com/en-US/dotnet/api/microsoft.net.http.server.response.hasstarted?view=aspnetcore-1.1
Each response consis of two parts: Header and Body
These two being sent together to the client, first the headers than the body. So during development, the only opportunity to set any value on the response object that affects the headers is up to the point at which you start sending the body.
As long as you begin sending the body of the response you can no longer change the headers because they are sent as the first part of the response just before the body begins sending.
I have .net core project and add stackify prefix to monitor requests, but in response prefix show only headers but not body of response. It is possible to see all response body?
On prefix site I found information:
It can capture incoming post data, it can also capture the response and the response headers and part of the response body. Right now, we limit that to only be a certain amount of characters so if it’s returning something larger, it won’t capture all of it.
It is possible to change this?
There is not a way to change this at the moment if the response body is too large it will not show up in the traces.
Stackify has an Ideas portal that you can make suggested changes to, their COO gets notified when a new request has been made and when a request has been up voted by several clients. He takes each request into good consideration and arranges them into Stackify's road map. Also you can subscribe to the ideas to keep updated on its progress.
https://ideas.stackify.com
I'm relatively new to WCF services, so I apologize in advance if I'm missing the obvious. My business uses EasyPost as our shipping solution, and I've written a WCF service to handle the shipping status webhook calls from EasyPost, described here: https://www.easypost.com/docs/webhooks
Briefly, EasyPost sends an update object as JSON via POST. The problem is that it sends several different types of (non-configurable) updates to the same service method, and I'm finding it difficult to write a DataContract that encompasses all the possibilities. For example, if the argument it sends is a tracking number update, update.result.status will be a string value; if it's a batch status update, update.result.status will be an object. It's a bit of a mess.
I tried handling just the update type that I care about and returning a 400 status code on the others, but EasyPost interprets that as an outage and drops my service as a webhook endpoint.
From what I've read, it looks like I could abandon the comforts of a Data Contract in favor of using a System.ServiceModel.Channels.Message parameter as a catch-all, then parse the message manually. That doesn't strike me as a wise/clean solution, though.
I'd be grateful for any alternatives.
This is probably not the best way I could have handled this, but it works.
I have an HTTP Module that identifies whether the incoming request is for the proper service method, and if so, converts the ContentType header from "application/json" to "text/plain".
My service method accepts the content body as a System.IO.Stream parameter. By converting the stream to a byte[] and then to a string, I end up with the raw JSON string sent by EasyPost.
After that, it's just a matter of using Newtonsoft.Json to attempt to deserialize the JSON string into the expected Type.
Even if the deserialization fails, I can still log the data and send a success response to the caller. That's good enough for my purposes.
I'm getting a 406 error when trying to use RestSharp to post a request to a third-party application. I'm new to REST, so I have to admit I didn't even know you could add headers. I tried adding these, but I'm still getting the same issue:
var client = new RestClient(myURL);
RestRequest request = new RestRequest("restAction", Method.POST);
request.AddHeader("Accept", "text/plain");
request.AddHeader("Content-Type", "text/plain");
request.AddParameter("parameter1", param1);
request.AddParameter("parameter2", param2);
var response = client.Execute(request);
From what I've read, this may be dealing with a header named "accept". Is that right?
Any idea what could be going on?
In general in HTTP, when a client makes a request to a server, it tells the server what kinds of formats it's prepared to understand (accept). This list of acceptable formats is what the Accept header is for. If the server can't respond using any of the media types in the Accept header, it will return a 406. Otherwise, it will indicate which media type it chose in the Content-Type header of the response. Putting "*/*" in the Accept header tells the server that the client can handle any response media type.
In my original comment to your question, I said that RestSharp looks like it's including "*" in the Accept header by default, but looking closer I see now that it's actually not. So, if you don't override the Accept header like you've done here, the default header value is "application/json","application/xml","text/json","text/x-json","text/javascript","text/xml", and it appears the server you're talking to doesn't speak any of these media types.
If the server you're working with doesn't speak json or xml, I don't think you can use RestSharp, unless you create your own deserializer. I'm not sure if you can do this from the public API or if you'd have to modify the source yourself and recompile it for you own needs.
Since you're still getting HTTP errors from the server, I would recommend taking RestSharp out of the equation for right now, and just speaking HTTP directly to the server until you actually get a correct response from the server. You can use a tool like Fiddler to make a HTTP requests directly. When you send the request (for now in the debugging stage), send an Accept header of "*/*" to get around the 406. Once you've figured out what media types the server can send back to you, you should change this back to being a media type you know you can read and you know the server can send.
It sounds like the main issue here is really just not knowing the protocol of the server. If there's any documentation on the service you're talking to, I would read that very carefully to figure out what media types it's prepared to respond with and how to craft the URLs that it expects.
Perhaps I'm overlooking something, but can client WCF not handle a server response that isn't a 200? For example, I'm trying to consume a service that returns a 400 when you asked for something naughty, but the body of the response is still a perfectly good and consumable SOAP message. It does the same for requested data that doesn't exist, returning a 404 but still having good hints about what the problem is. The WCF proxy seems to just puke and I can't get at the underlying body of the message.
Is that really how it rolls?
The only way to do this is to capture the protocol exception and then manually unserialize the envelope. The channel is hard coded to always throw a fault anytime an non 200 web response.