GameMaker runner crashes when making HTTP requests - json

I recently got back into using GameMaker:Studio, and hoo boy have there been some massive updates since I last used it! In fact the last time I used it they only had Windows and HTML5 as export options...
Anyway, eager to try out some of the new stuff, I decided to take a shot at the native HTTP functions, since they looked very promising.
I did a test using http_post_string() to great effect, sending a JSON string to my server and getting a JSON string back. The returned string actually represented an object with a single property, "echo", which contained the HTTP request that had been made, just to see what GM:S was sending.
I didn't like that it sent Content-Type: application/x-www-form-urlencoded when it was quite clearly JSON, and I wanted the ability to set my own User Agent string so that the server could know which game was talking to it without having to pass an extra parameter.
So I re-created the same request using the lower-level http_request() function. Everything looked fine, so I tested it.
It crashed. Like, no error messages or anything, just a total crash and Windows had to force-close it.
So here I am with code that by all rights should work fine, but crashes when run...
///send_request(file,ds_map_data,callback_event_id)
var request = ds_map_create();
request[? "instance"] = id;
request[? "event"] = argument2;
if( !instance_exists(obj_ajax_callback)) {
instance_create(0,0,obj_ajax_callback);
}
var payload = json_encode(argument1);
var headers = ds_map_create();
headers[? "Content-Length"] = string_length(payload);
headers[? "Content-Type"] = "application/json";
headers[? "User-Agent"] = obj_ajax_callback.uastring;
var xhr = http_request("https://example.com/"+argument0,"POST",headers,payload);
with(obj_ajax_callback) {
active_callbacks[? xhr] = request;
}
ds_map_destroy(headers);
obj_ajax_callback is an object that maintains a ds_map of active requests, and in its HTTP event it listens for those requests' callbacks and reacts along the lines of with(request[? "instance"]) event_user(request[? "event"]) so that the calling object can handle the response. This hasn't changed from the fully working http_post_string() attempt.
Any idea what could be causing this crash?

The reason why this crashes is because you are sending the Content-Length header as a real instead of a string. If you change your line to
headers[? "Content-Length"] = string(string_length(payload));
It should work.

Related

Apache HttpClient 4.5: Why does the second package wait for the ack of the first package?

I am using apache http client in version 4.5.13 within my java application to send a post request. I used following line of code to set up the http client.
SocketConfig socketConfig = SocketConfig.custom()
.setSoKeepAlive(true)
.setTcpNoDelay(true)
.build();
ConnectionConfig connectionConfig = ConnectionConfig.custom()
.setMalformedInputAction(CodingErrorAction.IGNORE)
.setUnmappableInputAction(CodingErrorAction.IGNORE)
.setCharset(Consts.UTF_8)
.setMessageConstraints(messageConstraints)
.build();
RequestConfig defaultRequestConfig = RequestConfig.custom()
.setCookieSpec(CookieSpecs.DEFAULT)
.setExpectContinueEnabled(true)
.setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM, AuthSchemes.DIGEST))
.setContentCompressionEnabled(true)
.build();
BasicHttpClientConnectionManager connectionManager = new BasicHttpClientConnectionManager();
connectionManager.setSocketConfig(socketConfig);
connectionManager.setConnectionConfig(connectionConfig);
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(connectionManager)
.setDefaultRequestConfig(defaultRequestConfig)
.build();
And I am sending the data via
CloseableHttpResponse response = httpClient.execute(postRequest);
The issue I am experiencing is that when I look how the messages are send (using tshark) I can see that the application data is split in two messages. The first one leaves my system around 0.5ms after the httpClient.execute(postRequest), but the second part is send around 10ms-20ms after the first one. It looks like the second part is waiting to receive the ack for the first part of the message. I tried to change a a lot of configurations (buffer sizes, TcpNoDelay, different TLS ...) but cannot figure out what is causing this behavior.
I also tried http.net client to send post requests. With this client the message was also split in two messages but they where both send right after each other (with around 0.3ms delay).
I am pretty new to network so I would appreciate a helpful answer and apologize upfront if I did not explain it very well (I do not know all the specific wordings).
Thanks
Try disabling expect-continue handshake.

Interrupted downloads when downloading a file from Web Api (remote host closed error 0x800704CD)

I have read near 20 other posts about this particular error, but most seem to be issues with the code calling Response.Close or similar, which is not our case. I understand that this particular error means that typically a user browsed away from the web page or cancelled the request midway, but in our case we are getting this error without cancelling a request. I can observe the error just after a few seconds, the download just fails in the browser (both Chrome and IE, so it's not browser specific).
We have a web api controller that serves a file download.
[HttpGet]
public HttpResponseMessage Download()
{
//
// Enumerates a directory and returns a Read-only FileStream of the download
var stream = dataProvider.GetServerVersionAssemblyStream(configuration.DownloadDirectory, configuration.ServerVersion);
if (stream == null)
{
return new HttpResponseMessage(HttpStatusCode.NotFound);
}
var response = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StreamContent(stream)
};
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = $"{configuration.ServerVersion}.exe";
response.Content.Headers.ContentType = new MediaTypeHeaderValue(MediaTypeNames.Application.Octet);
response.Content.Headers.ContentLength = stream.Length;
return response;
}
Is there something incorrect we are doing in our Download method, or is there something we need to tweak in IIS?
This happens sporadically. I can't observe a pattern, it works sometimes and other times it fails repeatedly.
The file download is about 150MB
The download is initiated from a hyperlink on our web page, there is no special calling code
The download is over HTTPS (HTTP is disabled)
The Web Api is hosted on Azure
It doesn't appear to be timing out, it can happen just after a second or two, so it's not hitting the default 30 second timeout values
I also noticed I can't seem to initiate multiple file downloads from the server at once, which is concerning. This needs to be able to serve 150+ businesses and multiple simultaneous downloads, so I'm concerned there is something we need to tweak in IIS or the Web Api.
I was able to finally fix our problem. For us it turned out to be a combination of two things: 1) we had several memory leaks and CPU intensive code in our Web Api that was impacting concurrent downloads, and 2) we ultimately resolved the issue by changing MinBytesPerSecond (see: https://blogs.msdn.microsoft.com/benjaminperkins/2013/02/01/its-not-iis/) to a lower value, or 0 to disable. We have not had an issue since.

why DeferredResult ends on setResult() on trying to use SSE

i am trying to implement a Server Sent Events (SSE) webpage which is powered by Spring. My test code does the following:
Browser uses EventSource(url) to connect to server. Spring accepts the request with the following controller code:
#RequestMapping(value="myurl", method = RequestMethod.GET, produces = "text/event-stream")
#ResponseBody
public DeferredResult<String> subscribe() throws Exception {
final DeferredResult<String> deferredResult = new DeferredResult<>();
resultList.add(deferredResult);
deferredResult.onCompletion(() -> {
logTimer.info("deferedResult "+deferredResult+" completion");
resultList.remove(deferredResult);
});
return deferredResult;
}
So mainly it puts the DeferredResult in a List and register a completion callback so that i can remove this thing from the List in case of completion.
Now i have a timer method, that will periodically output current timestamp to all registered "browser" via their DeferredResults.
#Scheduled(fixedRate=10000)
public void processQueues() {
Date d = new Date();
log.info("outputting to "+ LoginController.resultList.size()+ " connections");
LoginController.resultList.forEach(deferredResult -> deferredResult.setResult("data: "+d.getTime()+"\n\n"));
}
The data is sent to the browser and the following client code works:
var source = new EventSource('/myurl');
source.addEventListener('message', function (e) {
console.log(e.data);
$("#content").append(e.data).append("<br>");
});
Now the problem:
The completion callback on the DeferredResult is called on every setResult() call in the timer thread. So for some reason the connection is closed after the setResult() call. SSE in the browser reconnects as per spec and then same thing again. So on client side i have a polling behavior, but i want an kept open request where i can push data on the same DeferredResult over and over again.
Do i miss something here? Is DeferredResult not capable of sending multiple results? i put in a 10 seconds delay in the timer thread to see if the request only terminates after setResult(). So in the browser the request is kept open until the timer pushes the data but then its closed.
Thanks for any hint on that. One more note: I added async-supported to all filters/servlets in tomcat.
Indeed DeferredResult can be set only once (notice that setResult returns a boolean). It completes processing with the full range of Spring MVC processing options, i.e. meaning that all you know about what happens during a Spring MVC request remains more or less the same, except for the asynchronously produced return value.
What you need for SSE is something more focused, i.e. write each value to the response using an HttpMessageConverter. I've created a ticket for that https://jira.spring.io/browse/SPR-12212.
Note that Spring's SockJS support does have an SSE transport which takes care of a few extras such as cross-domain requests with cookies (important for IE). It's also used on top of a WebSocket API and WebSocket-style messaging (even if WebSocket is not available on either the client or the server side) which fully abstracts the details of HTTP long polling.
As a workaround you can also write directly to the Servlet response using an HttpMessageConverter.

Error sending data to a HTTPS server with as3httpclientlib

I'm trying to send some data from flash to a server. I was doing it with a test server and everything was ok. But when I change to test it into a real server it send me an error: " got Alert! Type=22" So I searched about it and I discover that its because the real server runs on HTTPS and the test runs on HTTP. So, reading the documentation of the as3httpclienlib library that I am using, I found that there is a bug with some HTTPS servers and cause some errors and don't leave flash send more than 40kb of data, so that throws the error Type 22 -> Record overflow
This only happens with TLS Sockets so I think that the solution is change the TLSSocket to a SSLSocket.
This is the code that I use to send the data to the server:
var client:HttpClient = new HttpClient();
var uri:URI = new URI("http://www.snee.com/xml/crud/posttest.cgi");
var variables:Array = [{name:"fname", value:"FirstName1"}, {name:"lname", value: "LastName1"}];
client.listener.onData = function(event:HttpDataEvent):void {
// Notified with response content in event.bytes as it streams in
};
client.listener.onComplete = function(event:HttpResponseEvent):void {
// Notified when complete (after status and data)
};
client.postFormData(uri, variables);
How can I change this sockets?
Does anyone have an example?
Is this the solution of the problem?

Is delegating JSON.parse to web worker worthwile (in Chrome Extension/FF Addon)?

I am writing a Chrome Extension which stores great deal of data in browser's localStorage and parses it on every page load. Now as the size of data increases, page load time/performance starts degrading. So I thought delegating the parsing to a web worker. But I am doubtful if it is worthwile. What I can do is pass my string to be parsed to worker like this.
worker.postMessage(localStorage['myObj']);
And I plan to parse this string into JSON and send it back to the main thread, like so
worker.onMessage(function(myObj){
//Then Play around with my object here.
});
But as I googled on the performance aspect of this method, including message posting and listening overheads, and the fact that some browser's don't allow sending JSON objects in the message and some serialize it automatically while sending, I doubt if this method is worthwile.
Since my app is just a Chrome Extension and also a Firefox Addon, I am concerned with just these two browsers. Can anyone suggest me if this method is suitable for these two browsers?
The currently-accepted answer is simply incorrect. It's entirely feasible to do what you asked about, example below.
Whether it's worth doing is something you'll have to check with real data in your real scenario. There's overhead associated with sending the JSON text to the worker and having it send back the parsed result (which may well involve some under-the-covers serialization, though it's probably not JSON), and modern browsers parse JSON very quickly.
I suspect the overhead isn't worth it, but perhaps on huge JSON strings, if the browser's native serialization mechanism is either much faster than JSON or takes place on a thread other than the main UI thread, perhaps it could be.
Example of using a worker to parse JSON:
// This stands in for 'worker.js':
var blob = new Blob([
'this.onmessage = function(message) {\n' +
'postMessage(JSON.parse(message.data));\n' +
'};'
], { type: "text/javascript" });
var workerUrl = URL.createObjectURL(blob);
// Main script:
var w = new Worker(workerUrl/*"worker.js"*/);
w.onmessage = function(message) {
display("Got response: typeof message.data: " + typeof message.data);
display("message.data.for = " + message.data.foo);
};
display('Posting JSON \'{"foo":"bar"}\' to worker');
w.postMessage('{"foo":"bar"}');
function display(msg) {
var p = document.createElement('p');
p.innerHTML = String(msg);
document.body.appendChild(p);
}
body {
font-family: monospace;
}
Result:
Posting JSON '{"foo":"bar"}' to worker
Got response: typeof message.data: object
message.data.for = bar
Only strings, not objects, can be passed to and from WebWorkers. If you parse a string into a JSON object within a WebWorker, you will need to stringify the object and then reparse it when passing it from the worker to your main script. Obviously, this will cause the JSON to be double-parsed unnecessarily and so is a bad idea.
2017 Update: More than just strings are allowed now. See some of the (much newer) answers and comments for reference.