F# with Http.fs - not able to execute GraphQL APIs - f#

I don't see any good documentation about how to execute GraphQL APIs using F# with Http.fs
Kindly share if you have the correct syntax available or point to the correct documentation for the same. I was trying with the Star Wars API given here: https://www.rithmschool.com/blog/an-introduction-to-graphql-queries
URL: https://swapi.graph.cool
Header: 'Content-Type': 'application/json'
JSON Body:
query {
Film (title:"A New Hope" ) {
director
characters {
name
}
}
}
Expected Response same as: https://swapi.graph.cool/

I'm not familiar with Http.fs, but here is a small working example of calling the API using the F# Data Http utility:
Http.RequestString
( "https://swapi.graph.cool",
httpMethod="POST", headers=[ HttpRequestHeaders.ContentType("application/json") ],
body=TextRequest("{\"query\": \"{ allFilms { title } }\"}") )
The main thing is that the body needs to be a JSON value where the actual query is a string stored in a record with a field named "query", i.e. {"query": "...."}.

Related

Alternative of "oneOf" construct in OpenApi 2.0 JSON

I am trying to create a JSON that will be parsed with OpenApi 2.0 swagger definition in Microsoft Power Automate Custom connector.
This is the JSON i have currently
"connectionParameters" : {
"param1" : "value1",
"param2" : "value2"
}
I want to provide an alternative connection parameter schema, in which user has the option to choose from a set of params to provide value. This can be achieved in OpenAPI 3.0 in the following way:
"connectionParameters" : {
anyOf : [
{
"param1" : "value1",
"param2" : "value2"
},
{
"alternateparam1" : "value1",
"alternateparam2" : "value2"
}
]
}
How can this be achieved in OpenAPI 2.0? "anyOf" is not available in OpenAPI 2.0 definition. I have explored the "discriminator" construct but couldn't find any implementation that I can provide with my JSON schema.
Personally, I think the approach you're trying with v3.0 would be a little confusing for the end user as I don't really understand what they'd actually be selecting in a dropdown persay.
I think your best bet (given you're limited anyway) is to use the ENUM keyword to define a basic list of values that when selected and passed into your API, you do the work in the background to select the more advanced objects that you've listed in your question.
https://swagger.io/docs/specification/data-models/enums/

Unable to authenticate on Crypto.com API C# REST API

Crypto.com offers an API where supposedly you could access their exchange platform. However, their documentation is extremely poor and inaccurate in terms of C# examples. I am unable to authenticate my REST calls using C#.
For all the private (account related) calls you need to sign your requests by adding a sig parameter to your payload JSON.
A simplified version of my code that calculates the sig parameter for the private/get-account-summary method looks like this (.net50):
private static string GetSignature()
{
string sigPayload = "private/get-account-summary" + 1 + API_KEY + "currencyCRO" + DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
var hash = new HMACSHA256(Encoding.UTF8.GetBytes(API_SECRET));
var computedHash = hash.ComputeHash(Encoding.UTF8.GetBytes(sigPayload));
return Convert.ToHexString(computedHash);
}
, while the request which makes use of this signature looks like this:
POST https://api.crypto.com/v2/private/get-account-summary
{
"id": "1",
"method": "private/get-account-summary",
"api_key": "[api_key]",
"params": {
"currency": "CRO"
},
"nonce": "1615048530368",
"sig": "1A7C7183CAF2E71F7F7DAB6A5C7F74319E692F2638710292BDB4FDFAC6C864D6"
}
As far as I know, I've correctly applied their algorithm for creating the signature and also used the correct parameters to call the method in question (https://exchange-docs.crypto.com/spot/index.html#private-get-account-summary). However, the response that I get tells me that I'm doing something wrong:
{
"id": 1,
"method": "private/get-account-summary",
"code": 10002,
"message": "UNAUTHORIZED"
}
I'm starting to have doubts that the API even works for private methods. Their support is awful and sent me to read the documentation again. I would appreciate any help in any language. If I at least hear that somebody else did it in another language I could use their example to figure out what I'm doing wrong.
The last line in the sample needs to be changed like this:
Convert.ToHexString(computedHash).ToLower();
In the end I followed my own advice and tried to call the service using one of the other sample languages. When I used JavaScript (which had a way better sample in the documentation) I've noticed the the resulting sig was lower case.

Retrieve parameter from a Jenkins REST query

The following REST query will return parameters of the last successful build of a job:
https://localhost/job/test1/lastSuccessfulBuild/api/json
I'd be interested to retrieve one of the parameters of this build, the BUILD_VERSION:
{
"_class": "org.jenkinsci.plugins.workflow.job.WorkflowRun",
"actions": [
{
"_class": "hudson.model.CauseAction",
"causes": [
{
"_class": "hudson.model.Cause$UpstreamCause",
"shortDescription": "Started by upstream project \"continuous-testing-pipeline-for-nightly\" build number 114",
"upstreamBuild": 114,
"upstreamProject": "continuous-testing-pipeline-for-nightly",
"upstreamUrl": "job/continuous-testing-pipeline-for-nightly/"
}
]
},
{ },
{
"_class": "hudson.model.ParametersAction",
"parameters": [
{
"_class": "hudson.model.StringParameterValue",
"name": "BUILD_VERSION",
"value": "1.1.15"
Is there a way to retrieve the BUILD_VERSION (1.1.15) directly using the REST Api or do I have to parse manually the json string ?
Thanks
Yeah you can get the value,But it will only work for XML API :(
The JSON API will return a simplified json object using Tree :)
So Jenkins provides you with api (XML,JSON,PYTHON) from which you can read the Jenkins related data of any project. Documentation in detail is provide in https://localhost/job/test1/lastSuccessfulBuild/api
In that it clearly states that
XML API - Use XPath to control the fragment you want.For example, ../api/xml?xpath=//[0]
JSON API - Use tree
Python API - Use st.literal_eval(urllib.urlopen("...").read())
All the above can be used to get a specific fragment/piece from the entire messy data that you get from the API.
In your case, we will use tree for obvious reasons :)
Syntax : tree=keyname[field1,field2,subkeyname[subfield1]]
In order to retrieve BUILD_VERSION i.e. value
//jenkins/job/myjob/../api/json?tree=lastSuccessfulBuild[parameters[value]]
The above should get you what you want, but a bit of trail and error is required :)
You can also refer here for a better understanding of how to use Tree in JSON API
https://www.cloudbees.com/blog/taming-jenkins-json-api-depth-and-tree
Hope it helps :)
Short answer: No.
Easiest way to programmatically access any attribute exposed via the JSON API is to take the JSON from one of Jenkins supported JSON APIs (in your case: https://localhost/job/<jobname>/lastSuccessfulBuild/api/json)
Copy the resultant JSON into http://json2csharp.com
Generate the corresponding C# code. Don't forget to create a meaningful name for top level class.
Call RestAPI programmatically from C# using RestSharp.
Deserialise the json to the C# class you defined in 2 above.
Wammo, you have access to the entire object tree and all its values.
I used this approach to write an MVC5 ASP.NET site I called "BuildDashboard" to provide all the information a development team could want and answered every question they had.
Here is an example with a public jenkins instance and one of its builds in order to get "candidate_revision" parameter for "lastSuccessfulBuild" build:
https://jenkins.qa.ubuntu.com/view/All/job/account-plugins-vivid-i386-ci/lastSuccessfulBuild/parameters/
https://jenkins.qa.ubuntu.com/view/All/job/account-plugins-vivid-i386-ci/lastSuccessfulBuild/api/xml?xpath=/freeStyleBuild/action/parameter[name=%22candidate_revision%22]/value

Eve - Is it possible to unset a key from a document?

In a schema with optional values such as code in the example:
'code': {
'type': 'string',
},
'name': {
'type': 'string',
'required': True,
},
'email': {
'type': 'string',
'required': True
}
Let's say there's an inserted document with a value for code. Can I unset the code key like mongodb $unset does, using Eve somehow?
One way to achieve this is to setup a default projection for the endpoint.
Limiting the Fieldset Exposed by the API Endpoint
By default API responses to GET requests will include all fields defined by the corresponding resource schema. The projection setting of the datasource resource keyword allows you to redefine the fields.
people = {
'datasource': {
'projection': {'username': 1}
}
}
The above setting will expose only the username field to GET requests, no matter the schema defined for the resource.
Another option is to leverage MongoDB Aggregation Framework itself. Just set the endpoint so that a aggregation is performed before data is returned to the client. The following should work (see the docs for details):
posts = {
'datasource': {
'aggregation': {
'pipeline': [{"$unset": "code"}]
}
}
}
You need Eve v0.7 for aggregation support.
I doubt you can do it with a PATCH request, but a PUT request should do.
import requests
# get original doc
resp = requests.get(document_url)
# prepare a new document
doc = resp.json()
new_doc = {k: v for k, v in doc.items() if not k.startswith('_')}
del new_doc['code']
# overwrite the complete document
resp = requests.put(document_url, json=new_doc, headers={'If-Match': doc['_etag']}

Elasticsearch: aggregation of URLS

I want my elasticsearch / Kibana4 to give me an overview which pages of my website are viewed most. I have a field "request" but since the URLs listed there contain parameters, I get a false list of the top requests
Example:
/search?query=123
/search?query=234
Each request is shown as a single request
but
home/foobar
home/foobar
is listed with 2 requests and is the top request in this case.
How can I tell elasticsearch to aggregate the requests that contain parameters?
There are number of ways to solve this.
One would be setting the url field as not_analyzed and then using script to parse out the unwanted value.
A sample script can be found here -
{
"aggs": {
"urls": {
"terms": {
"field": "url",
"script" : "_value.split("?")[0]"
}
}
}
}
Another approach would be to add a multifield and then remove the part after '?' using custom analyzer . You can achieve this by removing anything after '?' using pattern replace tokenizer

Resources