RESTful API: get/set one "global" single resource without id - api

TL;DR
In my current API, I've got two endpoints to handle the context:
GET /context/get
POST /context/set '{"id": "123"}'
What's the recommended way of having this global, id-less state accessible from RESTful API?
Please assume that the context concept can't be changed.
Background
Let's say I've got a user that is logged. He's by default assigned to a context that he can change.
After the context change, all the subsequent API calls will return different data, according to the context.
Example:
// Backend
Context = "Poland"
then
$ curl -X GET http://api.myapp.com/cities
will respond:
{
"cities": [{
"id": "1",
"name": Warszawa"
}, {
"id": "2",
"name": Wrocław"
}]
}
However, if you change the context:
// Backend
Context = "USA"
then, the same URL:
$ curl -X GET http://api.myapp.com/cities
should return the different set of data:
{
"cities": [{
"id": "3",
"name": New York City"
}, {
"id": "4",
"name": Boston"
}]
}
Question
As the context is just a global state on the backend side, it doesn't have an id. It doesn't belong to any collection either. Still, I want it to be accessible in the API. There are three possible solutions I see:
Solution #1 - existing
Set a context
$ curl -X POST http://api.myapp.com/context/set '{"id": "123"}'
Get a context
$ curl -X GET http://api.myapp.com/context/get
This one doesn't really feel like a RESTful API and still, on the frontend side, I have to mock the id (using ember-data). And the resource name is singular instead of plural.
Solution #2 - mocking the id
Set a context
$ curl -X POST http://api.myapp.com/context/1 '{"contextId": "123"}'
Get a context
$ curl -X GET http://api.myapp.com/context/1
Here I mock the id to always equal to one but I feel that it's super hacky and certainly not self-explanatory... Moreover, I've got a name conflict: id vs contextId. And the resource name is singular instead of plural.
Solution #3 - actions
Set a context
$ curl -X POST http://api.myapp.com/context/actions/set '{"id": "123"}'
Get a context
$ curl -X GET http://api.myapp.com/context/actions/get
This is very similar to the first one but using actions that could be a part of my whole API design (taken from e.g. gocardless. Still, I'll have a problem how to model it on the frontend side nicely. And the resource name is singular instead of plural again.
Is there any #4 option? How should I address this problem?
Thanks!

Your three solutions are RPC, not REST. Not only they are not stateless, but setting a resource to some other resource by setting an id is very RCP'ish.
A RESTful solution, if you really want to go that way, is to set the context in a header. The client should send a header like X-ContextId or something like that, and you determine the request context you need from that.
However, don't worry too much about being RESTful if that's not what your application requires. I recommend reading the answer here: SOAP vs REST (differences)

What's the recommended way of having this global, id-less state
accessible from RESTful API?
A RESTful API is by definition stateless, no client context should be stored on the server between requests.
If you want your API to be RESTful, you'll have to pass this id with each request.

Related

Fiware Entities and STH

I am using the Orion Context Broker, an IoT Agent and Cygnus to handle and persist the data of several devices into a MongoDB. It's working, but I don't know if I'm doing it in the Fiware way, because after reading the documentation I am confused yet about some things:
I don't completely understand the difference between an Entity and an IoT Entity (or device?). My guess is that is a matter of how they provide context data and the nature of the entity modelled, but I would be grateful if someone could clarify it. I am especially confused because the creation of each entity type is different (it seems that I can't initialize an IoT entity at creation time, which I can when dealing with a regular Entity).
I can only persist the data of IoT Entities. Is it possible to have a Short Term History of a regular Entity?
I don't understand why the STH data is repeating attributes that have not changed. If I have an IoT Entity with two attributes, 'a' and 'b', and I modify both of them, a STH entry is created for each one, which is fine. However, if then I change the value of attribute 'b', two more registers are created: one for 'a' (which hasn't changed and is reflecting the same value that it already had) and one for 'b'. Could someone explain to me this behavior?
1. Entities vs IoT Entities
I assume that what you mean by an IoT entity is the entry made by the IoT Agent upon receiving a sensor reading from a provisioned device.
Logically there is no difference between an entity created and maintained by an IoT Agent and an entity created and maintained by any other service making NGSI request to the context broker.
Your so-called IoT Entity is merely a construct where an IoT agent does all the heavy lifting for you and converts the data coming from a device in a propitiatory format into the NGSI standard.
2. Short Term History of a regular Entity
To create Short Term History you will need a separate Generic Enabler such as STH-Comet or QuantumLeap. Both of these enablers receive updates from Orion using the subscriptions mechanism. If you set up your IoT data using one fiware-service header and set up your non-IoT data using another fiware-service you can easily set up a subscription to differentiate between the two.
e.g. the following subscription:
curl -iX POST \
'http://localhost:1026/v2/subscriptions/' \
-H 'Content-Type: application/json' \
-H 'fiware-service: iotdata' \
-H 'fiware-servicepath: /' \
-d '<body>'
Will only apply to entities with the iotdata service path, which would be created when you provision your IoT service.
3. Repeating attributes that have not changed.
The <body> of the subscription can be used to narrow down the conditions under which the historical data is persisted.
The entities, conditions and the attrs are the important part of the subject
subject": {
"entities": [
{
"idPattern": "Motion.*"
}
],
"condition": {
"attrs": [
"count"
]
}
},
"notification": {
"http": {
"url": "http://quantumleap:8668/v2/notify"
},
"attrs": [
"count"
],
"metadata": ["dateCreated", "dateModified"]
},
"throttling": 1
}'
The subscription defined above will only fire if the count attribute is changed and only persist the count attribute. If you do not limit your attrs then multiple lines will be persisted to the database. Similarly if you do not limit the condition then multiple entries of count will be persisted when other attributes are updated.

Wit AI response for API requests

I'm using wit ai for a bot and I think it's amazing. However, I must provide the customer with screens in my web app to train and manage the app. And here I found a big problem (or maybe I'm just lost). The documentation of the REST API is not enough to design a client that acts like the wit console (not even close). it's like a tutorial of what endpoints you can hit and an overview of the parameters, but no clean explanation of the structure of the response.
For example, there is no endpoint to get the insights edge. Also and most importantly, no clear documentation about the response structure when hitting the message endpoints (i.e. the structure the returned entities: are they prebuilt or not, and if they are, is the value a string or an object or array, and what the object might contain [e.g. datetime]). Also the problem of the deprecated guide and the new guide (the new guide should be done and complete by now). I'm building parts of the code based on my testing. Sometimes when I test something new (like adding a range in the datetime entity instead of just a value), I get an error when I try to set the values to the user since I haven't parsed the response right, and the new info I get makes me modify the DB structure at my end sometimes.
So, the bottom line, is there a complete reference that I can implement a complete client in my web app (my web app is in Java by the way and I couldn't find a client library that handles the latest version of the API)? Again, the tool is AWESOME but the documentation is not enough, or maybe I'm missing something.
The document is not enough of course but I think its pretty straightforward. And from what I read there is response structure under "Return the meaning of a sentence".
It's response in JSON format. So you need to decode the response first.
Example Request:
$ curl -XGET 'https://api.wit.ai/message?v=20170307&q=how%20many%20people%20between%20Tuesday%20and%20Friday' \
-H 'Authorization: Bearer $TOKEN'
Example Response:
{
"msg_id": "387b8515-0c1d-42a9-aa80-e68b66b66c27",
"_text": "how many people between Tuesday and Friday",
"entities": {
"metric": [ {
"metadata": "{'code': 324}",
"value": "metric_visitor",
"confidence": 0.9231
} ],
"datetime": [ {
"value": {
"from": "2014-07-01T00:00:00.000-07:00",
"to": "2014-07-02T00:00:00.000-07:00"
},
"confidence": 1
}, {
"value": {
"from": "2014-07-04T00:00:00.000-07:00",
"to": "2014-07-05T00:00:00.000-07:00"
},
"confidence": 1
} ]
}
}
You can read more about response structure under Return the meaning of a sentence

Wso2 scim/Users endpoint brings less attributes

Using the wso2/scim/Users endpoint as described in doc i am supposed to get a response like this one
{
"schemas":[
"urn:scim:schemas:core:1.0"
],
"totalResults":2,
"Resources":[
{
"id":"0032fd29-55a9-4fb9-be82-b1c97c073f02",
"userName":"hasinitg",
"meta":{
"lastModified":"2016-01-26T16:46:53",
"created":"2016-01-26T16:46:53",
"location":"https://localhost:9443/wso2/scim/Users/0032fd29-55a9-4fb9-be82-b1c97c073f02"
}
},
{
"id":"b228b59d-db19-4064-b637-d33c31209fae",
"userName":"pulasthim",
"meta":{
"lastModified":"2016-01-26T17:00:33",
"created":"2016-01-26T17:00:33",
"location":"https://localhost:9443/wso2/scim/Users/b228b59d-db19-4064-b637-d33c31209fae"
}
}
]
}
But i need some extra info for every user and doing subsequent requests for every user using the id to get the extra information (like an email) is too bad.
Is it possible to configure the endpoint response so that i get the information needed for the users in one request ?
You should be able to do this with SCIM extensions.
This blog post has more details.
In WSO2 Identity server 5.3.0, you can achieve this by using the attributes query parameter.
eg. Following request will list all users along with their given names in a single call.
curl -k --user admin:admin 'https://localhost:9443/wso2/scim/Users?attributes=givenname'
Please refer the post here for more details.

How to Use getMaintenanceWindows method by using a SoftLayer REST API

please tell me how to get available maintenance windows by using a SoftLayer REST API.
I tried it in the following way, but it did not work.
curl -K support -d #Maintence.json -X POST https://api.softlayer.com/rest/v3/SoftLayer_Provisioning_Maintenance_Window/getMaintenceWindows
When executing the command, the following error message is displayed:
{"error":"End date must be a later date than begin
date.","code":"SoftLayer_Exception"}
The contents of the JSON file are described below:
{
"parameters":[
{
"beginDate": "2016-12-22T00:00",
"endDate": "2016-12-29T00:00",
"locationId": 138124,
"slotsNeeded" : 1
}]
}
The proper API to use here is SoftLayer_Provisioning_Maintenance_Window::getMaintenanceWindows() as opposed to the misspelled getMaintenceWindows
The API payload is still the same.
curl -K support -d #Maintence.json -X POST https://api.softlayer.com/rest/v3/SoftLayer_Provisioning_Maintenance_Window/getMaintenanceWindows
{
"parameters":[
"2016-12-22T00:00",
"2016-12-29T00:00",
138124,
1
]
}
When making API calls to the softlayer API, the parameters are not named, just listed in order that matches the documentation.
You just need to send the parameters (It's not necesary to define them in an object), so try with this json:
{
"parameters":[
"2016-12-22T00:00",
"2016-12-29T00:00",
138124,
1
]
}
References:
SoftLayer_Provisioning_Maintenance_Window::getMaintenceWindows

(Softlayer api)How to get endpoints from object storage in softlayer?

How can I get connection information of clusters in softlayer? I need public and private authentication urls for all clusters.
It seems that softlayer doesn't support the /v1/endpoints api of open stack api.
And I can see the getObjectStorageConnectionInformation api in Network Storage.. But don't know how to use it.
Try to use the following method:
SoftLayer_Network_Storage::getObjectStorageConnectionInformation, it will display the information of clusters and their endpoints (public and private)
To use this method, you need to provide an Object Storage's identifier, you can retrieve these identifiers (Object Storage identifiers), with the following REST request:
https://$username:$apiKey#api.softlayer.com/rest/v3/SoftLayer_Account/getHubNetworkStorage
Method: Get
Note: Replace $username and $apiKey with your own information.
You will retrieve a result like this:
{
"accountId": 123456
"capacityGb": 5000
"createDate": "2015-01-20T16:21:02-04:00"
"guestId": null
"hardwareId": null
"hostId": null
"id": 41111111
"nasType": "HUB"
"password": ""
"serviceProviderId": 1
"storageTypeId": "15"
"upgradableFlag": true
"username": "SLOS123456-10"
...
Then, you can get object storage connection with the following Rest request (Use the "id" value from the previous request)
https://$username:$apiKey#api.softlayer.com/rest/v3/SoftLayer_Network_Storage/41111111/getObjectStorageConnectionInformation
Method: Get
Note: Replace $username, $apiKey and 41111111 value with your own information
Some important references:
Managing SoftLayer Object Storage Through REST
APIs
An Introduction to Object
Storage
I'm using Advanced REST client for Chrome