What is the correct way for a WebSockets server using HttpListener and System.Net.WebSockets to support multiple subprotocols?
I am using HttpListener to create an HttpListenerContext. On receiving a request with IsWebSocketRequest true the code calls AcceptWebSocketAsync with the subprotocol name as the parameter.
If the client request is for a different subprotocol then an exception is raised, which is to be expected.
There's no version of AcceptWebSocketAsync() that accepts a list of subprotocols and if I make two asynchronous calls to AcceptWebSocketAsync() with different subprotocols, only the latter is effective.
Edit 14 March
To clarify, I'm looking for support for the Sec-WebSocket-Protocol header such that the framework accepts a websockets upgrade based on finding a common subprotocol between those requested by the client and those supported by the server, and then tells the calling code in some way which (single) subprotocol has been agreed. (For example, in libwebsockets, you provide one callback per subprotocol.)
You have access to HttpListenerContext which has the Request property. It returns an instance of HttpListenerRequest which in turn has the Headers property. Headers returns a collection of name/value pairs. You should find there Sec-WebSocket-Protocol header.
Now you have the list of subprotocols requested by a client. You also know what subprotocols are known by a server so you easily perform matching.
However, to be honest I didn't try this approach and I'm aware that it is not a straightforward solution.
Related
Just wondering if there is a way to enforce through an Attribute in ASP.NET Core to check if the HTTP header value belongs of the to a set given values (e.g. application/json, application/xml)
I know there is the ProducesAttribute (https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.producesattribute?view=aspnetcore-2.1 ):
[Produces("application/json", "application/xml")]
But it's more about the supported content types and not really about the Accept header analysis.
I would have expected something similar which would return a 406 HTTP code if the value of the Accept header is not:
[Accept("application/json", "application/xml")]
If there is not such attribute out of the box, how can I create one?
You can use [Consumes("application/json", "application/xml")].
Such an attribute is unnecessary. The Accept header is simply a way for the client to specify a preference for a particular response type, and the client is free to ask for whatever it wants. It's on the server to determine how to actually respond, and if it doesn't support a particular content type, then it simply returns a 415 Unsupported Media Type response. Otherwise, it will return the first content type it actually supports according to the order of the content types in the client's Accept header.
FWIW, it's important to understand that HTTP and the underlying IP protocols are intentionally designed to allow loose communication between client and server. The very terminology of a "request", implies this nature. The server cannot and should not force any behavior on the client and vice versa. All either can do is specify their preferences and then negotiate (another key term) a response for a particular request.
Long and short, you cannot stop a client from asking for things like a particular content-type. However, the server can respond that it does not support the given type if that's the case.
If I have a hub method that accepts parameters
e.g.
public IObservable<MyStreamItem> StreamData(SomeRequestData request)
{}
How do I propogate validation errors in the request?
An actual http request is only made when the socket connection is established.
So subsequent calls to Hub methods dont pass through any middleware. They are just frames/messages in the open websocket.
I've had a look at this package which is for the previous version of Signalr (for the full .net framework)
https://github.com/AGiorgetti/SignalR.Validation
This uses a HubPipelineModule which doesn't seem to exist in the new .net core Signalr.
Is there an appropriate place in the pipeline that I can tap into to do the validation?
Or should it be done in the hub method itself? And if so, how would you conditionally return a structured set of errors, as opposed to what the actual return type is meant to be?
thanks
There are currently no HubPipelineModules in SignalR alpha but we're looking at an equivalent for preview 2. Today, you'd need to do it in the method and potentially throw an error to get it back to the client.
I am new to WCF services and currently testing out things.
I have got a little REST API, which has several methods. Some of them require a user context (session), some others don't. At login, each user gets a session token. The client should supply this token and his user ID on every request via HTTP headers.
At the moment, I wrote a method for getting those two headers and validate the session, calling it on every method which will need a user context. This seems kinda nasty if the API gets bigger.
Is there a better approach for doing this?
You can leverage of following solutions:
Custom class deriving IClientMessageInspector/IDispatchMessageInspector for client and service respectively. Then you add its instance to MessageInspectors. Advantage of having messageInspector is that it's applied to single endpoint so regardless of having many endpoints exposed (both SOAP and REST), messageInspector can be associated only with single one. Whenever message is either received or sent, AfterReceive or BeforeSent method is invoked respectively. There you retrieve headers and if token does not match any expected you can throw an exception. Such a way out provides separation between exposed contract and background checks such as token validation.
Custom class deriving IOperationInvoker. Within custom operation invoker you explicitly call method and thanks to it you can examine headers (OperationContext.Current.IncomingMessage) before any method gets invoced.
I brought up only concepts, extensive information and examples can be looked up on Internet.
I want to know what is the best way to avoid the reinsertion of data in ASP.net.
I am currently doing
Response.Redirect('PageURL');
Thanks in Advance
Don't put your insertion code in the Page_Load method, or if you are, make sure you are checking Page.IsPostBack first.
Yes, normally we have an identity autoincrement number id, wich should be sent back to your form after the insertion. So you just have to check on server if that number is > 0 and execute an update instead of an insert.
Your redirect solution is valid. This pattern is called Post/Redirect/Get.
Post/Redirect/Get (PRG) is a web development design pattern that
prevents some duplicate form submissions, creating a more intuitive
interface for user agents (users). PRG implements bookmarks and the
refresh button in a predictable way that does not create duplicate
form submissions.
When a web form is submitted to a server through an HTTP POST request,
a web user that attempts to refresh the server response in certain
user agents can cause the contents of the original HTTP POST request
to be resubmitted, possibly causing undesired results, such as a
duplicate web purchase.
To avoid this problem, many web developers use the PRG pattern[1] —
instead of returning a web page directly, the POST operation returns a
redirection command. The HTTP 1.1 specification introduced the HTTP
303 ("See other") response code to ensure that in this situation, the
web user's browser can safely refresh the server response without
causing the initial HTTP POST request to be resubmitted. However most
common commercial applications in use today (new and old alike) still
continue to issue HTTP 302 ("Found") responses in these situations.
Use of HTTP 301 ("Moved permanently") is usually avoided because
HTTP-1.1-compliant browsers do not convert the method to GET after
receiving HTTP 301, as is more commonly done for HTTP 302.[2] However,
HTTP 301 may be preferred in cases where it is not desirable for POST
parameters to be converted to GET parameters and thus be recorded in
logs.
http://en.wikipedia.org/wiki/Post/Redirect/Get
I'm trying to get the raw data sent to IIS using a HttpHandler. However, because the request is an "GET"-request without the "Content-Length" header set it reports that there is no data to read (TotalBytes), and the inputstream is empty. Is there any way I can plug into the IIS-pipeline (maybe even before the request is parsed) and just kind of take control over the request and read it's raw data? I don't care if I need to parse headers and stuff like that myself, I just want to get my hands on the actual request and tell IIS to ignore this one. Is that at all possible? Cause right now it looks like I need to do the alternative, which is developing a custom standalone server, and I really don't want to do that.
Most web servers will ignore (and rarely give you access to) the body of a GET request, because the HTTP semantics imply that it is to be ignored anyway. You should consider another method (for example POST or PUT).
See this question and the link in this answer:
HTTP GET with request body