Navigation

    • Register
    • Login
    • Search
    1. Home
    2. Braeburn
    3. Posts
    • Profile
    • More
      • Following
      • Followers
      • Topics
      • Posts
      • Best
      • Groups

    Posts made by Braeburn

    RE: Empty response body from GET or POST HTTP request

    Hi @zipit!

    Our product supports multiple Cinema versions down to R16. We already have a working solution by using Python 2.x with urllib2. We wanted to switch to a pure Maxon based HTTP solution from R21 upwards. This worked out so far, except for the problem with the empty response body. The server responds with a 401 status code and it sends detailed informations about the failed authorization in the response body, which we would like to process. I'm aware this procedure is not based on an official standard but it is a very common procedure. So, we might need to use our Python based solution for R21 and S22 and switch to the Maxon solution for R23 and above.

    Best regards,

    Tim

    posted in Cinema 4D SDK •
    RE: Empty response body from GET or POST HTTP request

    Hi @zipit!

    Thanks for the comprehensive reply!
    Yes, your solution seems to produce a different result for R21. The body is unfortunately missing in the error message in R21:

    header-content-length: 52
    header-httpcode: 404
    header-httpmessage: Not Found
    errorMessage: invalid http response 404. Not Found (https://:[email protected]/test)
    
    err.GetMessage(): invalid http response 404. Not Found (https://:[email protected]/test)
    

    I need to get access to the (JSON encoded) response body because the server is responding with detailed informations about what exactly went wrong in different situations. Approximating this information from the httpcode and httpmessage is not sufficient in my case. I guess there is currently no solution for R21.

    BTW: From my experience it is pretty common to process the response body in case of some errors. I processed such responses in JavaScript based clients and the responses came from .NET Core, Python FastAPI, Go and WordPress based servers. You might also get problems if you only count on a returned status code. As an example: In a JavaScript based client which uses fetch() (which is a living standard) to make a HTTP request, you would get a Response object with an attribute Response.status. Unfortunately Response.status is not supported on Chrome and Firefox on Android and you might also look at the response body in such a case. See: https://developer.mozilla.org/en-US/docs/Web/API/Response/status

    Thank you very much!

    Best regards,

    Tim

    posted in Cinema 4D SDK •
    Empty response body from GET or POST HTTP request

    Hi everyone,

    I'm sending POST and GET http requests to a server via maxon::Url and maxon::FileUtilities::ReadFileToMemory(serverURL, charArray).
    The charArray will be sucessfully filled with the response body if the server responds with a status code 200 (OK) after the request has been sent with ReadFileToMemory(serverURL, charArray) . If the server responds with an error code like 401 (Unauthorized) the ReadFileToMemory() function unfortunately also returns an error, even if the client / server - communication was successfull. The main problem is that the response body (charArray) will be empty in such a case, even if the response header ("content-length") shows that a response body with a specific size was sent. I need to process the content of the response body if the server responds with a status code other than 200 (OK) after a POST request, which is a common approach in web development.

    Is the response body empty by design in such a case, or is this a bug?

    I prepared a small example which sends a GET request to the service https://httpstat.us.
    A request like https://httpstat.us/401 will respond with the body "401 Unauthorized" which will also be reflected in the response header:"Content-Length: 16".
    This can be observed with a tool like Postman (https://www.postman.com/downloads/), but the example code below will unfortunately result in an empty response body.

    Any ideas how I can get access to the response body? Thanks in advance!

    Best regards,

    Tim

    #include "maxon/network_url.h"
    #include "maxon/network_ip_ssl.h"
    #include "maxon/network_ip.h"
    #include "maxon/file_utilities.h"
    
    
    static maxon::Result<void> ProducesAnEmptyResponseBody()
    {
    	maxon::Url serverURL{ String("https://httpstat.us/401") };
    
    	// Set the request headers
    	maxon::DataDictionary requestHeaders;
    	requestHeaders.Set(maxon::Data(String("Content-Type")), maxon::Data(String("application/json"))) iferr_ignore();
    
    	iferr (serverURL.Set(maxon::URLFLAGS::HTTP_ADDITIONAL_REQUEST_HEADER, requestHeaders))
    	{
    		ApplicationOutput("Error 1: @", err);
    		return err;
    	}
    
    	// Setup a dictionary for the response headers
    	maxon::DataDictionary responseHeaders;
    	iferr (serverURL.Set(maxon::URLFLAGS::HTTP_RESPONSE_HEADER, &responseHeaders))
    	{
    		ApplicationOutput("Error 2: @", err);
    		return err;
    	}
    
    	// Sends the request and retrieves the response in a memory buffer.
    	// The response body will be stored in a char array.
    	// The response headers (includes the http status code)
    	// will be stored in the previously set response header dictionary.
    	maxon::BaseArray<maxon::Char> charArray;
    	iferr (maxon::FileUtilities::ReadFileToMemory(serverURL, charArray))
    	{
    		ApplicationOutput("Error 3: @", err);
    	}
    
    	// Store the response body as a string.
    	String responseBody = maxon::String(charArray);
    	ApplicationOutput("responseBody = '@'", responseBody);
    
            // Extract the status code from the response header, etc...
            // ApplicationOutput("responseHeaders = '@'", responseHeaders);
    
    	return maxon::OK;
    }
    
    posted in Cinema 4D SDK •
    RE: ObservableFinished() does not pass a job result to an observer

    Thank you very much, Manuel!
    This is a working solution for the issue and it helped me a lot!

    Best regards,
    Tim

    posted in Cinema 4D SDK •
    RE: ObservableFinished() does not pass a job result to an observer

    Thanks for your reply Manuel (@m_magalhaes)!

    One of my first ideas for a solution was to use a this capture for the lambda, but in my case the function which creates the HttpRequestJob and adds the Observer is a static function and I got the following compiler error: 'this' can only be used as a lambda capture within a non-static member function.
    So I replaced the this capture with an & capture:

    httpRequestJob.ObservableFinished().AddObserver([&]()
    {
    	iferr (HttpResponse response = httpRequestJob.GetResult())
    	{
    		ApplicationOutput("Error: @", err);
    	}
    
            ...
    
    }) iferr_return;
    

    This will compile, but GetResult() returns the following error at runtime: nullptr [job.h(1354)] The returned HttpResponse will be empty / uninitialized. It seems the result might not exist anymore when the observer gets called. httpRequestJob.GetResult() works fine if called outside of the lambda, so I had the feeling that getting the result inside the lambda was not the right way to go. I was expecting that ObservableFinished() would pass the result instead.

    Any more ideas?

    Best regards,
    Tim

    posted in Cinema 4D SDK •
    ObservableFinished() does not pass a job result to an observer

    Hi everyone,

    I would like to use Cinemas job system to send multiple HTTP requests asynchronous / in parallel. I have created a custom HttpRequestJob which will return a custom HttpResponse struct.

    After the job will be enqueued (and therefore started) I can sucessfully ask for the HTTP response with:

    HttpResponse response = httpRequestJob.MoveResult() iferr_return;

    Instead of asking the job for a result I would like to get a callback function called after the job has finished, because this would better fit into our current plugin architecture. I would like to add an observer to httpRequestJob.ObservableFinished().

    The problem is:
    I will not get the result from the job (an HttpResponse object) passed to the observer / callback function. The callback function has the following signature:

    static void RequestCallback(HttpResponse httpResponse)

    It seems the following does not work because the callback function has a parameter:

    httpRequestJob.ObservableFinished().AddObserver(RequestCallback);

    It also does not work when I provide a lambda with a HttpResponse or const HttpResponse& argument as an observer:

    httpRequestJob.ObservableFinished().AddObserver([](HttpResponse response)
    {
       // Doing something with the response ...
    }) iferr_return;
    

    It seems AddObserver() will only take a callback function without arguments in this case, but this way I cannot do any meaningful work with the observer.

    Any ideas how I can get access to the job result in an observer? Thanks in advance!

    Best regards,

    Tim

    PS: The job looks something like this:

    class HttpRequestJob : public maxon::JobInterfaceTemplate<HttpRequestJob, HttpResponse>
    {
    public:
    	HttpRequestJob() { };
    
    	HttpRequestJob(
    		const String &url,
    		const String &method,
    		const String &body,
    		const maxon::DataDictionary &headers)
    	{
    		_url = url;
    		_method = method;
    		_body = body;
    		_headers = headers;
    	}
    
    	maxon::Result<void> operator ()()
    	{
    		iferr (HttpResponse httpResponse = SendHttpRequest(_url, _method, _body, _headers, _description))
    		{
    			ApplicationOutput("@", err);
    			return err;
    		}
    
    		return SetResult(std::move(httpResponse));
    	}
    
    	const maxon::Char* GetName() const
    	{
    		return "HttpRequestJob";
    	}
    
    private:
    	maxon::String _url;
    	maxon::String _method;
    	maxon::String _body;
    	maxon::DataDictionary _headers;
    };
    
    posted in Cinema 4D SDK •
    RE: R19: SplitPolygon and Ngon indices

    @r_gigante Thank you very much for your help, Riccardo!

    The suggested method of calculating the ngon index works fine with the Modeling::SplitPolygon() function, but functions like Modeling::GetEdgeNgons() sometimes return unexpected indices, which seem to be based on a different logic.

    I have updated the demo plugin and also included an image (NgonIndexProblem.png) in the zip file, which explains the problem:

    https://files.frankwilleke.de/index.php/s/EpGg1TkdzIemWJl

    In this case Modeling::GetEdgeNgons() and Modeling::GetPointNgons() returns indices which seem to be a confusing mix of ngon and polygon indices (or indices with and without offsets).

    Do you have any more ideas?

    Thanks in advance,
    Tim

    posted in Cinema 4D SDK •
    RE: R19: SplitPolygon and Ngon indices

    Frank kindly uploaded the example plugin for me. I would like to add a few things. The strange behavior in Modeling::SplitPolygon() is just one of many confusing observations with ngon indices.

    For me the main questions are:
    What exactly is an ngon index?
    What needs to be done, to create an ngon index, which works consistently with all the ngon functions in the SDK?

    In the example above we assume that ngon indices start at 0, which seems to be incompatible with some of the methods in Cinema's Modeling class.

    If I use the Modeling::GetEdgeNgons() function to get the shared ngons of an edge, Cinema returns 9 as an index for the first ngon we want to split, and 10 for the next ngon we want to split. If I use those indices the Modeling::SplitPolygon() function works fine.

    So it seems the indices are somehow offsetted. Maybe ngon indices start after the polygon indices?

    On the other side, the polygon to ngon index conversions returned by the function PolygonObject::GetPolygonTranslationMap() seems to have no offsets and are not compatible with functions like Modeling::SplitPolygon() and Modeling::GetEdgeNgons().

    Is somebody able to clarify the general logic behind ngon indices in Cinema 4D?

    Thank you very much!
    Best regards
    Tim

    posted in Cinema 4D SDK •