How to automatically convert CSRF Tokens to HTTP request headers in Elm? - elm

I am writing a single page application in Elm to interface with a Django backend. The Django Rest Framework provides a CSRF token in a cookie but expects all requests to contain the token in an HTTP header.
Is there a way to declaratively instruct Elm to return the CSRF token as HTTP header with each request? E.g., along the line how I would configure it in JS/Axios:
axios.defaults.xsrfCookieName = 'csrftoken'
axios.defaults.xsrfHeaderName = "X-CSRFTOKEN"
There is an old SO question that implies to manually extract the token from the cookie and then use Http.send for each request. That would mean to wrap all HTTP request functions by hand.

Using version 2.0.0 of the elm/http library, you would need to use request in order to provide headers. It's fairly common for an application to use a customized version of these "base" methods that ask for whatever your environment requires.
get httpConfig route tagger decoder =
Http.request
{ method = "GET"
, headers = httpConfig.headers
, url = httpConfig.baseUrl ++ route
, body = Http.emptyBody
, expect = Http.expectJson tagger decoder
, timeout = Nothing
, tracker = Nothing
}
post httpConfig route value tagger decoder =
Http.request
{ method = "POST"
, headers = httpConfig.headers
, url = httpConfig.baseUrl ++ route
, body = Http.stringBody "application/vnd.api+json" (Encode.encode 0 value)
, expect = Http.expectJson tagger decoder
, timeout = Nothing
, tracker = Nothing
}

Related

OAuth2: Unable to Authenticate API request

Been tasked to export forms and items from Podio using the API. Trying to do this with straight Python and Requests instead of the canned API tool. Am successful at retrieving the access and refresh tokens, but am unable to make the simplest Get request. The response has the error:
"error_description":"Authentication as None is not allowed for this method"
Tried this with 2 versions of using OAuth2 in Requests, both return that response.
What is it trying to tell me? Aside from giving the token, is there any other authentication attributes required?
client = BackendApplicationClient(client_id=CLIENT_ID)
oauth = OAuth2Session(client=client)
token = oauth.fetch_token(token_url=auth_url, client_id=CLIENT_ID,
client_secret=CLIENT_SECRET)
print('token:', token)
access_token = token["access_token"]
api_url = base_url + 'user/status'
r = oauth.get(api_url)
print(r.text)
headers = {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
"Authorization": "Bearer " + token["access_token"]}
response = requests.get(api_url, headers=headers, verify=True)
print(response.text)
Here is full response:
{"error_parameters":{},"error_detail":null,"error_propagate":false,"request":{"url":"http://api.podio.com/user/status","query_string":"","method":"GET"},"error_description":"Authentication as None is not allowed for this method","error":"forbidden"}

Schedule refresh not working for web.contents based query

This is the message I get when I am trying to get the token data using web.contents query from "VMware vRealize Automation API":
There was an error when processing the data in the dataset.
Please try again later or contact support. If you contact support, please provide these details.
Data source error
{"error":{"code":"ModelRefresh_ShortMessage_ProcessingError","pbi.error":{"code":"ModelRefresh_ShortMessage_ProcessingError","parameters":
{},"details":[{"code":"Message","detail":{"type":1,"value":"Web.Contents failed to get contents from 'https://xxxxxxxxx.com/identity/api/tokens'
(404): Not Found"}}],"exceptionCulprit":1}}}
Table: GetToken.
The url passed to the first parameter of Web.Contents (authUrl = "https://xxxxxxxxx.com/identity/api/tokens") is accessible but always return the HTTP ERROR 405, probably
because this API uses a a JSON object in the request body parameter with the users credentials to obtain the Response.
API
My query
The main issues:
Your API uses HTTP POST verses GET, so you need to set Options[Content]
You can get refresh errors on the service unless you use Options[RelativePath]
You can "opt-in" to handling errors for specific HTTP Status codes, combined with Value.MetaData you get more detailed error messages.
Let it generate JSON for you from records and lists by using Query or Content parameters see: docs: Web.Contents
This is equivalent to your curl POST request
let
BaseUrl = "https://www.example.com",
Options = [
RelativePath = "/identity/api/tokens",
Headers = [
Accept="application/json"
],
Content = [
username = "username",
password = "password",
tenant = "tenant"
],
ManualStatusHandling = {400, 405}
],
// wrap 'Response' in 'Binary.Buffer' if you are using it multiple times
response = Web.Contents(BaseUrl, Options),
buffered = Binary.Buffer(response),
response_metadata = Value.Metadata(response),
status_code = response_metadata[Response.Status],
from_json = Json.Document(final_result)
in
from_json
I have related Web.Contents examples here, like Chaining Web.Contents requests: ninmonkeys.com/Power-Query-Custom-Functions-Cheat-Sheet

API Connect 5 - Error attempting to read the urlopen response data

I'm trying to create a REST API from a SOAP Service using IBM API Connect 5. I have followed all the steps described in this guide (https://www.ibm.com/support/knowledgecenter/en/SSFS6T/com.ibm.apic.apionprem.doc/tutorial_apionprem_expose_SOAP.html).
So, after dragging the web service block from palette, ensuring the correctness of endpoint and publishing the API, I have tried to call the API from the browser. Unfortunately, the API return the following message:
<errorResponse>
<httpCode>500</httpCode>
<httpMessage>Internal Server Error</httpMessage>
<moreInformation>Error attempting to read the urlopen response
data</moreInformation>
</errorResponse>
To testing purpose, I have logged the request and I have tried the request on SOAPUI. The service return the response correctly.
What is the problem?
In my case, the problem was in the backend charset (Content-Type: text/xml;charset=iso-8859-1).
For example, backend returns text/xml in German (or French). Api Connect cannot process character ΓΌ. It needs Content-Type: text/xml;charset=UTF-8.
I had a similar issue, in my case was the accept. if you have an Invoke and the content-type or the accept, is not matching the one of the request, or the response that you got, APIC is getting mad.
Please, check if the formats to send (contentType) and receive (accept) are the same of that your API expected. In my case the error occurs because the API returns a String and my default code is configured to receive a JSON body.
//define a JSON-PLAIN TEXT protocol
private HttpEntity<String> httpEntityWithBody(Object objToParse){
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer " + "xxx token xxx");
headers.set("Accept", MediaType.TEXT_PLAIN_VALUE);
headers.setContentType(MediaType.APPLICATION_JSON);
Gson gson = new GsonBuilder().create();
String json = gson.toJson(objToParse);
HttpEntity<String> httpEntity = new HttpEntity<String>(json, headers);
return httpEntity;
}
//calling the API to APIC...
ParameterizedTypeReference<String> responseType = new
ParameterizedTypeReference<String>(){};
ResponseEntity<String> result =
rest.exchange(builder.buildAndExpand(urlParams).toUri(), HttpMethod.PUT, httpEntityWithBody(myDTO), responseType);
String statusCode = result.getStatusCodeValue();
String message = result.getBody();

how to consume http post in elm with header and body

I am new in elm and try to consume web api using http post request with header and body using 0.17.1 version but did not get any documentation.
So any one help me to implement this functionality
The send method of the Http package gives you the possibility to create and send a custom request. For example, a post request could be something like
postRequest : Request
postRequest =
{ verb = "POST"
, headers =
[ ("Origin", "http://elm-lang.org")
, ("Access-Control-Request-Method", "POST")
, ("Access-Control-Request-Headers", "X-Custom-Header")
]
, url = "http://example.com/hats"
, body = empty
}
You can then create the Task that represent the request using the send function like
send defaultSettings postRequest

500 error on api request. works fine when called through browser

Hello I have an api which authenticates the user login . Now when I hit this rest service in my browser it displays the result but when I try to do this using my code it gives in 500 error. Please help me with this .
My Api: http://abhinavevent2014.sched.org/api/auth/login?api_key=1309658400d57c8cfc6081f8361de52c&username=abhinavm#test.com&password=test
string url = #"http://abhinavevent2014.sched.org/api/auth/login?api_key=1309658400d57c8cfc6081f8361de52c&username=abhinavm#test.com&password=test";
Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
WebRequest requestfriend = WebRequest.Create(url);
WebResponse responsefriend = requestfriend.GetResponse(); ( This is where it blows)
Stream streamResponse = responsefriend.GetResponseStream();
StreamReader streamReaderResponse = new StreamReader(streamResponse, encode);
jsonResult = streamReaderResponse.ReadToEnd();
return jsonResult.ToString();
You need to use User-Agent in the headers, as the documentation says:
You must also send requests with a User-Agent in the headers, as Sched
filters out requests with no User-Agent.
Sched API Doc
Browser automatically does that, so it can retrieve the data.