How to make a http request in a playground update function? - openapi

I want to make http requests from my elm program.
I use the openapi-generator https://eriktim.github.io/openapi-elm for the http requests:
https://github.com/eriktim/openapi-elm,
The only example I could find is this:
https://github.com/eriktim/openapi-elm/tree/master/example
There, a request has e.g. type Api.Request Api.Data.PlanetList and is converted with the send function: (Result Http.Error a -> msg) -> Request a -> Cmd msg.
The send function takes a function to convert the Request result to msg but but returns it wrapped in Cmd.
The update function has type
update : Msg -> Model -> ( Model, Cmd Msg )
So as long as the request is made in the update function and the result is put in the return value the framework will get msg out of Cmd.
Now I want to make requests in my program, but I'm using playground game as my main function (example) where the update function is update : Computer -> Model -> Model so the "trick" from the example project is not applicable. How can I still get the values from my request call then?

A Http request is a piece of data for the runtime to execute. If the Cmd is not passed to the runtime through the main update, the actual http call will never happen.
This is why you cannot have side-effects in simple programs (Playground and Browser.sandbox).

I'm not really sure what elm-playground is, but that's not the right starting point for a webapp such as you want to create, as it does not support Commands, such as Http requests.
You want to be using normal / standard Elm - see https://guide.elm-lang.org/install/elm.html and then you want to be building a Program based on Browser.document - https://guide.elm-lang.org/webapps/
Hope that gets you on your way

Related

Capture json response value and http status from cpprest sdk pplx task cpp to local variables

I want to write a generic function in cpp that gets JSON data using cpprestsdk and copy the http status response code and the JSON data. The calling method will use the json_resp and http_status codes. Later on, I want to further make this function more generic by passing the URL and use it to get data from different web services. Please let me know how I can accomplish this.
pplx::task<void> handleWebServerRequest( web::json::value json_resp, int *http_status)
{
..
http_client client(L"http://weburl.com:8000/getjsondata");
return client.request(methods::GET).then([](http_response response) -> pplx::task<json::value> {
// Store the http status code to be returned to calling function
*http_status = response.status_code();
..
if(response.status_code() == status_codes::OK) {
return response.extract_json();
}
return pplx::task_from_result(json::value()); }).then([](pplx::task<json::value> previousTask) {
try {
// capture json response to json_resp
json_resp = previousTask.get();
}
catch( const http_exception& e) {
// print error
}
});
}
In my research I have found that the only difference between using cpprest api to consume a PHP web service and a WCF web service is the function parameter. When consuming a PHP web service you can set the function parameter to an empty string. Where as when consuming a WCF service you need to pass it a function parameter-because the protocol for receiving requests and issuing responses in a WCF service is very different, but the process of sending requests and receiving responses is asynchronous so there will always be at least three modules, functions or tasks involved. One to make the request. The other to wait and receive the response and another to parse the data which is called asynchronously by the function that receives the response. I suppose you could put all three tasks into one function and use go to statements to execute each task, perhaps use some inline assembly to capture the response, and use pointers in place of parameters - but it is still three tasks anyway you slice it. The two others run in a thread and do not have access to the application data, but the last function that parses the data (the json object) which is called asynchronously you could make generic. I don't know which web services you want to consume, but I posted two samples on github-Example of Casablanca (cpprestsdk 2.9.1) consuming a PHP web service and Example of Casablanca (cpprestsdk 2.9.1) consuming a WCF (.net) web service. I believe this should get you off to a good start. To capture the json values you can convert your json values to std strings (as shown below) and then you can store them respectively in a local hashmap by adding a hashmap pointer argument to all three functions and passing a reference to the local hashmap variable from which ever function you are calling it from where they can be converted to what ever data type you need.
void get_field_map_json(json::value & jvalue, unordered_map <string, string> * hashmap)
{
if (!jvalue.is_null())
{
for (auto const & e : jvalue.as_object())
{
std::string key(conversions::to_utf8string(e.first));
std::string value(conversions::to_utf8string(e.second.as_string()));
(*hashmap)[key] = value;
}
}

Lambda + API Gateway: Long executing function return before task finished

I have a function in Lambda that executes for up to 30s depending on the inputs.
That function is linked to an API gateway so I am able to call it through POST, unfortunatly the API Gateway is limited to 30s exaclty, so if my function runs for longer I get an "internal server error" back from my POST.
I see 2 solutions to this:
Create a "socket" rather then a simple POST which connects to the lambda function, not sure if this is even possible or how would this work.
Return a notification to api gateway before the lambda function is actually finished. This is acceptable for my use case, but I am not sure again how would this work.
The function is coded in Python3.6 I therefore have access to the event and context object.
Return a notification to api gateway before the lambda function is actually finished. This is acceptable for my use case, but I am not sure again how would this work.
Unfortunately, you will not be able to return a result until the Lambda is finished. Otherwise, AWS will interrupt execution of Lambda if you try to do it, for example, via multithreading.
I suggest you create the following system:
API Gateway puts a request to Kinesis stream and returns a response of successfully putting. The response will contain SequenceNumber of the Kinesis Record. (How to do it)
Lambda is invoked by Kinesis Stream Event, processes the request and saves that your job is done (or completed result) to DynamoDB with SequenceNumber as id.
You invoke another API Gateway method and SequenceNumber to check the status of your job in DynamoDB (if necessary).
If you need just to run the Lambda without knowing of job result you can avoid using DynamoDB.
statut approach is nice, but I'd like to give you an alternative: AWS step functions. Basically it does what statut's solution does but it might be more easy to deploy.
All you have to do is to create an AWS Step Functions state machine that has your lambda function as its only task. AWS Step functions intrinsically works asynchronously, and has methods to know the status and, eventually, the result. Check the docs for more info.
A very simple solution would be for your lambda function to just asynchronously invoke another lambda function and then return a result to API Gateway.
Here's a real example of executing one lambda function asynchronously from another lambda function:
import json
import boto3
def lambda_handler(event, context):
payload = {}
##take the body of the request and convert to string
body = json.loads(event['body'])
##build new payload with body and anything else your function downstream needs
payload['body'] = json.dumps(body)
payload['httpMethod'] = 'POST'
payloadStr = json.dumps(payload)
client = boto3.client('lambda')
client.invoke(
FunctionName='container name',
InvocationType="Event",
Payload=payloadStr
)
return {
'statusCode': 200,
'body': json.dumps('Hello from Lambda!')
}
In this example, the function invokes the other one and returns right away.
invoke documentation: https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/lambda.html#Lambda.Client.invoke

Why does one HTTP GET request retrieve the required data and another retrieve []

I'm currently working on ng-admin.
I'm having a problem retrieving user data from my REST API (connected to a MongoDB) and displaying it.
I have identified the problem as the following:
When I enter http://localhost:3000/users into my browser, I get a list of all users in my database.
When I enter http://localhost:3000/users?_page=1&_perPage=30&_sortDir=DESC&_sortField=id,
I get [] as a result.
I am quite new to this, I used both my browser and the POSTMAN Chrome extension to test this and get the same result.
http://localhost:3000/users_end=30&_order=DESC&_sort=id&_start=0
This (/users_end) is a different request than /users.
It should be:
http://localhost:3000/users?end=30&_order=DESC&_sort=id&_start=0
Or, by looking at the other parameters:
http://localhost:3000/users?_end=30&_order=DESC&_sort=id&_start=0
with end or _end being the first parameter (mark the ?).
Update (it is ? and before the _, I have edited.):
If adding parameters to the request returns an empty list, try adding only one at a time to narrow down the problem (there's probably an error in the usage of those parameters - are you sure you need those underscores?).
Your REST API must have a way to handle pagination, sorting, and filtering. But ng-admin cannot determine exactly how, because REST is a style and not a standard. So ng-admin makes assumptions about how your API does that by default, that's why it adds these _end and _sort query parameters.
In order to transform these parameters into those that your API understands, you'll have to add an interceptor. This is all thoroughly explained in the ng-admin documentation: http://ng-admin-book.marmelab.com/doc/API-mapping.html

RxSwift - Fetch undetermined resources via HTTP

I have undetermined resources that need to be fetched from a server. I tried to accomplish this by using the repeatElement() and concat() operators like this:
repeatElement(0, CurrentThreadScheduler.instance).map({ _ -> Observable<[Task]> in
// API.getTasks() uses Alamofire to request data
return API.getTasks(loggedUser, after: loggedUser.taskPullTime)
}).concat().takeWhile({ (tasks) -> Bool in
return tasks.count > 0
})
Unfortunately, repeatElement will just emit an item without waiting for the old one to be handled. I think the reason is that Alamorfire executes in a private serial queue.
However, I cannot figure out how to solve this problem.
I used the strategy inspired from here in my Android project. Everything works fine because Retrofit init HTTP request in a synchronous manner.

store and setRequest

I have a jobque mechanism in ZF.
The jobque simlpy stores the the function call (Class, Method and params) and later executes it as CLI daemon. The daemon works, however at places the application looks for information from the request object, and when called from the CLI these places fail, or get no info.
I would like to store the original request object together with the job and when the job is processed set the request object back as if the job was done by the originall request, somethin along the line of the following pseudo code:
$ser_request = serialize(Zend_Controller_Front::getInstance ()->getRequest ());
-->save to db
-->retrive from db
$ZCF= new Zend_Controller_Front;
$ZCF::getInstance ()->setRequest (unserialize($ser_request))
The aim is to store and replay the jobs later withouth having to change the rest of the application.
Any suggestions how to do that?
I am not sure if this works, but here's an idea. Try to implement _sleep and _wakeup magic methods for the request object. Haven't tried it out, but maybe it's at least a starting solution.