The hub sends larger chunks than it receives them - signalr

I have the Hub which takes the file, saves into the private static property and later sends it file back to the caller user.
public class TestHub : Hub
{
private static string _file;
public async Task SendAudio(IAsyncEnumerable<string> stream)
{
var enumerator = stream.GetAsyncEnumerator();
await enumerator.MoveNextAsync();
_file = enumerator.Current;
}
public async IAsyncEnumerable<string> ReceiveFile([EnumeratorCancellation] CancellationToken cancellationToken)
{
yield return _file;
}
}
The problem occurs when I'm looking in the websocket panel.
The first red frame (send file) shows length is 57122 bytes.
The second red frame (receive file) shows length is 146515 bytes.
Why is the difference so great?

It looks like you're trying to send binary data. Json doesn't support binary data, instead you're supposed to base64 encode your data before giving it to Json, and on the server side you would either base64 decode it, or store it as a base64 blob. The reason you're seeing a difference here is that your client side is taking the bytes you gave it and just directly using them as their UTF8 value. However on the server side when it sends the same data back it will see that some of the UTF8 data isn't safe and will do some extra encoding to make sure it is safe, hence the different size.
If you want to avoid having to base64 encode your blobs, you can give the Message Pack protocol a try which supports byte[] directly. https://learn.microsoft.com/aspnet/core/signalr/messagepackhubprotocol?view=aspnetcore-3.1

Related

faild to build body in activemq

I want use ActiveMQ in .net core,i use Apache.NMS.ActiveMQ for doing this but I have problem.
I see this error in ActiveMQ admin console:
Cannot display ObjectMessage body. Reason: Failed to build body from bytes. Reason: java.io.StreamCorruptedException: invalid stream header: 00010000
thats part of my code for doing this:
private const String QUEUE_DESTINATION = "test-queue";
private IConnection _connection;
private ISession _session;
public MessageQueue()
{
IConnectionFactory factory = new ConnectionFactory("tcp://localhost:61616?wireFormat.maxInactivityDuration=5000000");
_connection = factory.CreateConnection();
_connection.Start();
_session = _connection.CreateSession();
}
IDestination dest = _session.GetQueue(QUEUE_DESTINATION);
using (IMessageProducer producer = _session.CreateProducer(dest))
{
var objectMessage = producer.CreateObjectMessage(newDoc);
producer.Send(objectMessage);
}
The fact that the admin console can't display the body of an ObjectMessage isn't really an error. It's the expected behavior. Remember, from the broker's perspective the message body is just an array of bytes. It could be text data (encoded many different ways), image data, custom binary data, etc. The broker has no idea how to decode it. It will try to display the body as text, but if it fails it won't try anything else.
To be clear, in order to see the contents of an ObjectMessage the web console would have to have the object's definition in order to deserialize it. There is no mechanism to tell the web console about arbitrary data formats so it can deserialize message bodies reliably (other than simple text). This is one reason, among many, to avoid ObjectMessage.
I recommend you use a simple text format (e.g. JSON, XML) to represent your data and send that in your message rather than using ObjectMessage.

How to send boolean value or int value in a http request body?

How to send a boolean value or an integer in http request body in dart? The documentation says that I can only send string, list or a Map. How to make it work for boolean or integer in Dart?
Try this approach which I use in my projects
void apiPost(){
var body = jsonEncode(
{
"string":"test",
"bool":true,
"int":1
});
http.post("url here",body: body,headers: {"Content-Type": "application/json"}).then((response) {
Map map = json.decode(response.body);
});
}
As you saw in the documentation, you can only send those three things: a byte array, a string or a map of string to string. In fact, in the end, you are just sending a byte array. The other options get converted to bytes before sending.
A string is converted to bytes by transforming it into bytes using utf-8 (or some other encoding specified by the content-type header).
A map of string to string is encoded to first as x-www-form-urlencoded and then to bytes. That encoding can, of course, only encode strings.
So the answer to your question really depends on where/how the server expects to receive the fields. If it's expecting them in a form, then it's your responsibility to convert, say, a boolean into whatever string the server expects. Maybe that's 'true'/'false' or '1'/'0' or something else. Make your map like this:
int someInt;
bool someBool;
var formData = <String, String>{
'an_int_value' : someInt.toString(),
'a_bool_value' : someBool.toString(), // assuming 'true'/'false' is OK
};
Also consider the possibility that your server requires a completely different encoding, like JSON. Then you would convert your map to JSON, then pass that as a string, setting the content-type appropriately.

Smart way to add parameters' signature with Square's Retrofit

`I need to contact an API which requires that every request contain the signature of all parameters and url + nonce.
Example:
#GET("/users/{type}")
public void getUsers(
#Path("type") String type,
#Query("sort") boolean sort)
I should add a X-Signature header with contains signature(nonce+"/users/"+type+"sort="+sort).
I thought I could do this with a RequestInterceptor's addHeader(String name, String value) but I can`t as the signature varies for every request.
Is there a smart way to do this with Retrofit or will I just have to manually sign every request?
Am I right in thinking that your signature is generated from [nonce]+[path]+[query params]
You could look at implementing a custom client and passing this into your RestAdapter.Builder().setClient(new CustomClient) method.
Something like CustomClient extends OkClient and then override the execute(Request) method. You will need to create a new Request object and pass that to super.execute(updatedRequest).
#Override
public Response execute(Request request) throws IOException {
List<Header> headers = new ArrayList<>();
// do work here to parse the request.getUrl() and extract path/params and generate the signature
headers.addAll(request.getHeaders());
headers.add(new Header("X-Signature", "signature"));
Request updated = new Request(request.getMethod(), request.getUrl(), headers, request.getBody());
return super.execute(updated);
}
If however there is no consistency to the generation of the signature then you will need to create the signature manually and add a #Header value in your call to your client.

returning a JSON formatted file via WCF

We've seen a number of posts relating to JSON data returns via WCF, but they all cover the aspect of converting object to JSON and then returning that object converted to JSON via the magic of attributes.
We've got a number of preformatted JSON files that we want to return via an WCF service. Essentially all we need to do is read the files in (or a cached copy of of the file) and then return the data as a string . I think ... It seems wasteful to read in the JSON file, serialize it to an object then deserialize back to JSON.. Any help on this?
When using the WebHttpBinding, this is as simple as creating a WebGet annotated method with a Stream return type:
[WebGet]
public Stream GetFile(Int32 someId)
{
//your logic to lookup or create the file here.
//Open the file (a MemoryStream would be acceptible as well if you were creating the data on the fly
Stream stream = File.OpenRead(yourFilePath);
//register an event to clean up the temporary file (if necessary)
OperationContext.Current.OperationCompleted += (s, e) =>
{
File.Delete(yourFilePath);
};
return stream;
}

Objects stored by riak-java-client end up as raw json when read by riak-python-client?

I might be confused about something, but when I store a custom object from the Java Riak client and then try to read that object using the Python Riak client, I end up with a raw json string instead of a dict.
However, if I store a the object in python, I am able to output a python dictionary when fetching that object.
I could simply use a json library on the python side to resolve this, but the very fact that I am experiencing this discrepancy makes me think that I am doing something wrong.
On the Java side, this is my object:
class DocObject
{
public String status; // FEEDING | PERSISTED | FAILED | DELETING
public List<String> messages = new ArrayList<String>();
}
class PdfObject extends DocObject
{
public String url;
public String base_url;
}
This is how I am storing that object in Riak:
public void feeding(IDocument doc) throws RiakRetryFailedException {
PdfObject pdfObject = new PdfObject();
pdfObject.url = doc.getElement("url").getValue().toString();
pdfObject.base_url = doc.getElement("base_url").getValue().toString();
pdfObject.status = "FEEDING";
String key = hash(pdfObject.url);
pdfBucket.store(key, pdfObject).execute();
}
And this is what I am doing in Python to fetch the data:
# Connect to Riak.
client = riak.RiakClient()
# Choose the bucket to store data in.
bucket = client.bucket('pdfBucket')
doc = bucket.get('7909aa2f84c9e0fded7d1c7bb2526f54')
doc_data = doc.get_data()
print type(doc_data)
The result of the above python is:
<type 'str'>
I am expecting that to be <type 'dict'>, just like how the example here works:
http://basho.github.com/riak-python-client/tutorial.html#getting-single-values-out
I am perplexed as to why when the object is stored from Java it is stored as a JSON string and not as an object.
I would appreciate if anybody could point out an issue with my approach that might be causing this discrepancy.
Thanks!
It would appear you've found a bug in our Python client with the HTTP protocol/transport.
Both the version you're using and the current one in master are not decoding JSON properly. Myself and another dev looked into this this morning and it appears to stem from an issue with charset parameter being returned from Riak with the content-type as Christian noted in his comment ("application/json; charset=UTF-8")
We've opened an issue on github (https://github.com/basho/riak-python-client/issues/227) and will get this corrected.
In the mean time the only suggestion I have is to decode the returned JSON string yourself, or using the 1.5.2 client (latest stable from pypy) and the Protocol Buffers transport:
client = riak.RiakClient(port=8087, transport_class=riak.RiakPbcTransport)
it will return the decoded JSON as a dict as you're expecting.

Resources