I am writing a TCP server app in Dart. When doing similar things in other languages, I've noticed that even if I send a byte buffer of size X, my onData() receive function will probably be called multiple times with smaller buffers that add up to X. If I'm not mistaken, this happens because of Flow Control. So usually my payload's header contains the payload size, and I use that to wait until I've read the full payload before processing it.
Do I have to handle this manually in Dart too? So far, I have not had issues and I've received the entire payload in a single call to onData(), but I'd rather ask.
I didn't have issues either, but you could start processing the data while the response is not yet fully received.
If the response is huge, all data needs to be buffered. This way you aren't able to receive data that is bigger than your available RAM. For example downloading a movie wouldn't be possible this way.
Yes. While I'm not sure the exact size of the data transferred to a request, there may be times when you have to completely drain the stream before accessing the data being sent via a POST or other method. (For the body of the http request). See the Creating a server section of the Dart Tutorial. In particular you can see how the stream is drained under Handling POST requests. Normally rather than writing back the pieces as the example shows, they are added directly to a buffer as follows:
var buff = [];
req.listen(buff.addAll,
onDone: () {
print('Received: ${String.fromCharCodes(buff)}');
});
See more information on HttpRequest class documentation.
As an alternative, you can use the http_server package which will automatically drain the stream for you and handle the data load properly depending on the headers which are passed with the request. It does this by applying a stream transformer to the incoming HttpRequests stream to convert them to HttpRequestBody. See below for an example. For more details see the HttpBodyHandler API.
HttpServer.bind(...).then((server) {
server.transform(new HttpBodyHandler())
.listen((HttpRequestBody body) {
// each request is now an HttpRequestBody
// which has already drained the stream
print(body.type);
print(body.body);
body.request.response..statusCode = HttpStatus.OK
..writeln('Got it!')
..close();
});
});
Related
For example (golang):
type {
Product struct {
Name string
}
Customer struct {
Name string
Products []*Product
}
}
Which is the correct behavior:
GRPC honor the *Product pointer and transfer it only once.
GRPC will transfer the same *Product as many times as it associated to different Customer.
Michael,
It is not clear on your message, but I am assuming that you will send a Customer as part of your request to a gRPC server.
Golang will marshal the struct into []byte (https://godoc.org/github.com/golang/protobuf/proto#Marshal), so the message will not have such thing as a pointer. It will be just an encoded message. (see
https://github.com/golang/protobuf/blob/master/proto/wire.go#L22).
gRPC is not a Golang thing, so a pointer on a side (e.g. server) does not mean it must be a point on the other side (e.g. client).
Finally, answering your question, the expected behavior is 2. However, you may take a deeper look into proto buff serialization (https://developers.google.com/protocol-buffers/docs/encoding). I have no idea how it works, but maybe the message is compressed, so repeated []bytes maybe be discarded.
gRPC newbie. I have a simple api:
Customer getCustomer(int id)
List<Customer> getCustomers()
So my proto looks like this:
message ListCustomersResponse {
repeated Customer customer = 1;
}
rpc ListCustomers (google.protobuf.Empty) returns (ListCustomersResponse);
rpc GetCustomer (GetCustomerRequest) returns (Customer);
I was trying to follow Googles lead on the style. Originally I had returns (stream Customer) for GetCustomers, but Google seems to favor the ListxxxResponse style. When I generate the code, it ends up being:
public void getCustomers(com.google.protobuf.Empty request,
StreamObserver<ListCustomersResponse> responseObserver) {
vs:
public void getCustomers(com.google.protobuf.Empty request,
StreamObserver<Customer> responseObserver) {
Am I missing something? Why would I want to go through the hassle of creating a ListCustomersResponse when I can just do stream Customer and get the streaming functionality?
The ListCustomersResponse is just streaming the whole list at once vs streaming each customer. Googles preference seems to be to return the ListCustomersResponse style all of the time.
When is it appropriate to use the ListxxxResponse vs the stream response?
This question is hard to answer without knowing what reference you're using. It's possible there's a miscommunication, or that the reference is simply wrong.
If you're looking at the gRPC Basics tutorial though, then I might have an inkling as to what caused a miscommunication. If that's indeed your reference, then it does not recommend returning repeated fields for streamed responses; your intuition is correct: you would just want to stream the singular Customer.
Here is what it says (screenshot intentional):
You might be reading rpc ListFeatures(Rectangle) as meaning an endpoint that returns a list [noun] of features. If so, that's a miscommunication. The guide actually means an endpoint to list [verb] features. It would have been less confusing if they just wrote rpc GetFeatures(Rectangle).
So, your proto should look more like this,
rpc GetCustomers (google.protobuf.Empty) returns (stream Customer);
rpc GetCustomer (GetCustomerRequest) returns (Customer);
generating exactly what you suspected made more sense.
Update
Ah I see, so you're looking at this example in googleapis:
// Lists shelves. The order is unspecified but deterministic. Newly created
// shelves will not necessarily be added to the end of this list.
rpc ListShelves(ListShelvesRequest) returns (ListShelvesResponse) {
option (google.api.http) = {
get: "/v1/shelves"
};
}
...
// Response message for LibraryService.ListShelves.
message ListShelvesResponse {
// The list of shelves.
repeated Shelf shelves = 1;
// A token to retrieve next page of results.
// Pass this value in the
// [ListShelvesRequest.page_token][google.example.library.v1.ListShelvesRequest.page_token]
// field in the subsequent call to `ListShelves` method to retrieve the next
// page of results.
string next_page_token = 2;
}
Yeah, I think you've probably figured the same by now, but here they have chosen to use a simple RPC, as opposed to a server-side streaming RPC (see here). I emphasize this because, I think the important choice is not the stylistic difference between repeated versus stream, but rather the difference between a simple request-response API versus a more complex and less-ubiquitous streaming API.
In the googleapis example above, they're defining an API that returns a fixed and static number of items per page, e.g. 10 or 50. It would simply be overcomplicated to use streaming for this, when pagination is already so well-understood and prevalent in software architecture and REST APIs. I think that is what they should have said, rather than "a small number." So the complexity of streaming (and learning cost to you and future maintainers) has to justified, that's all. Suppose you're actually fetching thousands of (x, y, z) items for a Point Cloud or you're creating a live-updating bid-ask visualizer for some cryptocurrency, e.g.
Then you'd start asking yourself, "Is a simple request-response API my best option here?" So it just tends to be that, the larger the number of items needing to be returned, the more streaming APIs start to make sense. And that can be for conceptual reasons, e.g. the items are a live-updating stream in time like the above crypto example, or architectural, e.g. it would be more efficient to start displaying results in the UI as partial data streams back. I think the "small number" thing you read was an oversimplification.
TL; DR I have an ASP.NET 5 (MVC 6) application and just trying to set a HTTP Content-Length header in order to avoid chunked response.
To my surprise, it happens that this is a quite tricky task to accomplish in ASP.NET 5. Everything is running on Kestrel which from ASP.NET 5 Beta7 supports writing chunked responses automatically when no content length is specified for the response.
There is a similar question here, but the difference is that the OP just wants to count a response size, while I need to ensure that the Content-Length header is sent within a response. Tried with many things so far, and the only thing that works is writing a custom Middleware:
public class WebApiMiddleware {
RequestDelegate _next;
public WebApiMiddleware(RequestDelegate next) {
_next = next;
}
public async Task Invoke(HttpContext context) {
using (var buffer = new MemoryStream()) {
var response = context.Response;
var bodyStream = response.Body;
response.Body = buffer;
await _next(context);
response.Headers.Add("Content-Length", new[] { buffer.Length.ToString()});
buffer.Position = 0;
await buffer.CopyToAsync(bodyStream);
}
}
}
However, this is highly inefficient since we are using additional memory while processing every request. Using a custom stream that just wraps around the context.Response.Body stream and additionally counts bytes doesn't work since the Microsoft team states that once the amount of data they're willing to buffer has been written, it goes out on the wire and they don't store it any more, so I can, at best, add Content-Length to the last chunk which is not the wished behavior - I want to avoid chunking completely.
Any help is highly appreciated!
p.s. I am aware that chunking is a regular feature of HTTP/1.1, but in my scenario it degrades performance so I want to avoid it without forcing the clients to send HTTP/1.0 requests.
You need to send header before sending response so you need to store whole response before sending it to determine length.
As you said context.Response.Body stream doesn't store to much before sending so overhead is not that big.
There is middleware that does similar thing: https://github.com/aspnet/BasicMiddleware/blob/master/src/Microsoft.AspNetCore.Buffering/ResponseBufferingMiddleware.cs it is very similar to what you wrote but supports additional features like IHttpBufferingFeature to allows other middleware control buffering.
Checking for bufferStream.CanSeek is there to make sure nobody already wrapped response stream into buffering stream and avoid double buffering.
For your second question: this place is middlware.
Im creating a Networking API and want people to be able to route requests to specific endpoints using a ServeMux. Instead of using a Server instance, I need to use my own low level ServerConn. This is because I am receiving both incoming HTTP requests and plain text data from the same port.
The problem, however, is that if I want to forward a request using my ServeMux, I would use it's ServeHTTP method. For this, I need to provide a ResponseWriter, which I don't know how to create an instance of since it is an interface, not a struct. Should a I create my own ResponseWriter struct? Is there one given by the Golang Standard Library? Or is there an alternate solution to this altogether?
I would avoid doing this altogether if at all possible. Mixing protocols on the same connection is bound to lead to hard-to-trace bugs, and unexpected behavior. If you really want to do it, and have all the http/1.1 mechanisms work correctly, leave as much as possible to the http package.
Since ResponseWriter is an interface, you would implement your own type to satisfy it. Look at the unexported response type in the http package for a full example. There's a lot to get right, and using it in combination with a ServerConn (which is documented as "do no use") is probably not a good idea.
The place to do this at a lower level would be in Accept inside the Server's net.Listener. Since you're going to have to parse the start of every request twice, you would need a net.Conn that can be "rewound" partly.
Make yourself a net.Listener that checks the start of the stream on a new connection, and if it looks like an http request, return a net.Conn that replays the first chunk you read off the wire on its first Reads. Something like:
type replayConn struct {
net.Conn
buf []byte
pos int
}
func (c *replayConn) Read(b []byte) (int, error) {
if c.pos < len(c.buf) {
n := copy(b, c.buf[c.pos:])
c.pos += n
return n, nil
}
return c.Conn.Read(b)
}
If the connection isn't http, then send the connection off to your other type of handler, and continue blocking on Accept.
I am writing a code for Client-Server and there are two possibilities.
The user will request a specific information A to be transmitted.
The user will request a specific information B to be transmitted.
I would like to identify what the client want in my server side and how the client will do that.
Any other ideas?
I know is quite old question but I think what will be a good idea is to use the Chain of Responsibility Design Pattern!
The idea is that you can use a single port and send your request to Receiver 1, Receiver 1 will decide if can handle this request if not, will pass the request to the Receiver 2, Receiver 2 will have to do the same decision and if can handle the request, then will send the response back to the Sender.
So we have the following properties:
One port is required
The Sender(or the Client in other words) is only aware of the 1st Receiver.
The responsible receiver will return a response directly to the sender/client even if the sender/client is not aware of that specific receiver.
Reduced coupling
Dynamically manage the request handlers.
Furthermore, at the end of the chain, you can add behavior to indicate something like a final response, or a default response if the request send has no responsible class to handle it.
UML
Example
Depending on the size of the information, you can always transmit both information through one pipe and then decipher the needed one on the user side
string data = // .. data transmitted.
string[] dataSplit = data.Split(SEPARATOR);
// dataSplit[0] is type of information
switch(dataSplit[0]) {
case 'Name':
...
break;
case 'OS':
...
break;
}
Do you understand ?