Error on Credentials handshake of Public Test Environement - shareandcharge

I am seeing the following error on step 3 Credentials handshake of OCN Node registration. (https://shareandcharge.atlassian.net/wiki/spaces/OCN/pages/265945122/OCN+Node+registration#3.-Credentials-handshake)
When I send the credentials handshake, I see the following error:
{
"status_code": 3001,
"status_message": "Failed to request from https://edrv-ocpi-dev.herokuapp.com/ocpi/versions: Cannot deserialize instance of `snc.openchargingnetwork.node.models.ocpi.OcpiResponse<java.util.List<snc.openchargingnetwork.node.models.ocpi.Version>>` out of START_ARRAY token\n at [Source: (String)\"[{\"status_code\":1000,\"data\":{\"versions\":[{\"version\":\"2.2\",\"url\":\"https://edrv-ocpi-dev.herokuapp.com/ocpi/2.2\"}]},\"timestamp\":\"2020-02-15T07:48:58.364Z\"}]\"; line: 1, column: 1]",
"timestamp": "2020-02-15T07:48:58.390914Z"
}
This is the request I am sending:
curl -X POST \
https://qa-client.emobilify.com/ocpi/2.2/credentials \
-H 'Accept: */*' \
-H 'Accept-Encoding: gzip, deflate' \
-H 'Authorization: Token 21c158fc-****-****-****-************' \
-H 'Cache-Control: no-cache' \
-H 'Connection: keep-alive' \
-H 'Content-Length: 297' \
-H 'Content-Type: application/json' \
-H 'Host: qa-client.emobilify.com' \
-H 'Postman-Token: 8cb3bcba-2cc0-4923-9290-04be261fb686,fe8e2916-ee94-4676-a60a-ad64e3869dcc' \
-H 'User-Agent: PostmanRuntime/7.19.0' \
-H 'cache-control: no-cache' \
-d '{
"token": "9e9cf68b-****-****-****-dcb7fcaa341e",
"url": "https://edrv-ocpi-dev.herokuapp.com/ocpi/versions",
"roles": [{
"party_id": "EDV",
"country_code": "NL",
"role": "EMSP",
"business_details": {
"name": "eDRV Technologies B.V."
}
}]
}'
I have setup a quick server on heroku as per step 2 in the tutorial. Here is what the versions endpoint code looks like:
app.get("/ocpi/versions", authorize, async (_, res) => {
res.send([{
status_code: 1000,
data: {
versions: [{
version: "2.2",
url: `${PUBLIC_URL}/ocpi/2.2`
}]
},
timestamp: new Date()
}])
})
Is there something I am missing in the request?

The original version of OCPI 2.2 contains an error. The bugfix branch contains the correct type: https://github.com/ocpi/ocpi/blob/release-2.2-bugfixes/version_information_endpoint.asciidoc
You can change your response to the following to make it work:
res.send({
status_code: 1000,
data: [{
version: "2.2",
url: `${PUBLIC_URL}/ocpi/2.2`
}],
timestamp: new Date()
})

Related

How to get PubSub message data in an API?

I want to get this kind of message json data from Pub/Sub
{
"message": {
"data": {
"from": "no-reply#example.com",
"to": "user#example.com",
"subject": "test",
"body": "test"
}
}
}
And parse its data to use for other service.
private parseMessage(message: Message) {
try {
const decoded = Buffer.from(message.data.toString(), 'base64').toString().trim();
return JSON.parse(decoded);
} catch (err) {
throw new BadRequestException(
'Parse Error: ' + message,
);
}
}
But when run the API got this error:
SyntaxError: Unexpected token � in JSON at position 0
at JSON.parse (<anonymous>)
at EventController.parseMessage (../myapp/src/api/posts/posts.controller.ts:44:18)
response: {
statusCode: 400,
message: 'Parse Error: [object Object]',
error: 'Bad Request'
},
status: 400
It seems this post isn't right:
curl -X 'POST' \
'http://localhost:3000/posts' \
-H 'Content-Type: application/json' \
-d '{
"message": {
"data": {
"from": "no-reply#example.com",
"to": "user#example.com",
"subject": "test",
"body": "test"
}
}
}'
Then how to make fake Pub/Sub message data?
I think you need to encode your data into Base64.
Base64 encoding schemes need to encode binary data that needs to be stored and transferred over media that are designed to deal with ASCII. This is to ensure that the data remain intact without modification during transport.
You can also refer to this GCP public documentation.
Eg. From the Doc:
# 'world' base64-encoded is 'd29ybGQ='
curl localhost:8080 \
-X POST \
-H "Content-Type: application/json" \
-d '{
"context": {
"eventId":"1144231683168617",
"timestamp":"2020-05-06T07:33:34.556Z",
"eventType":"google.pubsub.topic.publish",
"resource":{
"service":"pubsub.googleapis.com",
"name":"projects/sample-project/topics/gcf-test",
"type":"type.googleapis.com/google.pubsub.v1.PubsubMessage"
}
},
"data": {
"#type": "type.googleapis.com/google.pubsub.v1.PubsubMessage",
"attributes": {
"attr1":"attr1-value"
},
"data": "d29ybGQ="
}
}'

Query tensor in vespa.ai

Imitating: https://blog.vespa.ai/billion-scale-knn/
Command line:
curl -s -d '{"yql":"select * from user where {\"targetHits\":10}nearestNeighbor(approximate, q_binary_code);","ranking.features.query(q_binary_code)":[1,2,3,4,5,6,7,8,9,10],"hits":10}' -H "Content-Type: application/json" -X POST http://localhost:8080/search/ | jq .
Error message:
{
"root": {
"id": "toplevel",
"relevance": 1,
"fields": {
"totalCount": 0
},
"errors": [
{
"code": 4,
"summary": "Invalid query parameter",
"source": "content",
"message": "Expected a tensor value of 'query(q_binary_code)' but has [1,2,3,4,5,6,7,8,9,10]"
}
]
}
}
Question: How pass q_binary_code?
With recent Vespa versions, you can define the query tensor in the schema. It must be defined
schema code {
document code {
field id type int {..}
field binary_code type tensor<int8>(b[16]) {..}
}
rank-profile coarse-ranking {
inputs {
query(q_binary_code) tensor<int8>(b[16])
}
num-threads-per-search:12
first-phase { expression { closeness(field,binary_code) } }
}
You also must define the rank profile in the query request:
curl -s -d '{"yql":"select * from user where {\"targetHits\":10}nearestNeighbor(binary_code, q_binary_code);","ranking.features.query(q_binary_code)":[1,2,3,4,5,6,7,8,9,10],"hits":10, "ranking": "coarse-ranking"}' -H "Content-Type: application/json" -X POST http://localhost:8080/search/ | jq .

How to POST a Multipart form with image and a JSON object containing an array of objects using CURL

I am trying to post the following JSON object alongside with image data using curl:
{
"score_id": "153A6D67",
"inputs": [{
"type": "hits",
"value": "4"
},{
"type": "miss",
"value": "3"
}]
}
The best I have come so far is this:
curl --request POST "https://my-server/post-url" \
--header 'Accept: application/json' \
--form "score_id=153A6D67" \
--form 'inputs[]={"type":"hits","value":"4"}; type=application/json' \
--form 'inputs[]={"type":"miss","value":"3"}; type=application/json' \
--form "uploaded_image=#$IMAGE" # <<< IMPORTANT! this is an image!
The server implementation I am trying to hit, does not recognize the objects sent with the attribute inputs.
Any Idea what I am doing wrong?
Thank you very much for any direction.
You can try this
curl --location --request POST 'https://my-server/post-url' \
--header 'Content-Type: application/json' \
--data-raw '{
"score_id": "153A6D67",
"inputs": [{
"type": "hits",
"value": "4"
},{
"type": "miss",
"value": "3"
}]
}'
This is how I got it to work:
curl --request POST "https://my-server/post-url" \
--header 'Accept: application/json' \
--form "score_id=153A6D67" \
--form 'inputs[0][type]=hits' \
--form 'inputs[0][value]=4' \
--form 'inputs[1][type]=miss' \
--form 'inputs[1][value]=3' \
--form "uploaded_image=#$IMAGE"

swagger-js-codegen api is sending the wrong request header content-type

So I have newly upgraded to Swagger 2 from 1.x, and am experiencing an odd issue. One of my APIs is getting an incorrect content-type injected into the header and I have no idea where from, you can see below in the SwaggerJSON, The DELETE function even says it consumes application/json, but the CURL(copied from inspect panel) for it sends 'Content-Type: text/plain;charset=UTF-8'. I have provided the CREATE function as a cursory example to show that otherwise the similar apis work fine. I think this is an issue with swagger-js-codegen because if I put the same request into the api-docs it works fine, or of course my Java, or somewhere somehow my content-type header is getting set, but i have no idea how or where. Am I missing something? The API acts the same whether or not my JAVA claims 'consume = "application/json"' or not.
Swagger JSON
{
"/api/entities/{id}/labels": {
"delete": {
"consumes": [
"application/json"
],
"operationId": "deleteEntityLabel",
"parameters": [
{
"default": "16_appiniteDev",
"description": "The id of the entity to be edited",
"in": "path",
"name": "id",
"required": true,
"type": "string"
},
{
"description": "The label/labels to be deleted",
"in": "body",
"name": "labels",
"required": true,
"schema": {
"items": {
"type": "string"
},
"type": "array"
}
}
],
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/ResponseEntity"
}
},
"204": {
"description": "No Content"
},
"401": {
"description": "Unauthorized"
},
"403": {
"description": "Forbidden"
}
},
"summary": "Deletes Labels for Entities",
"tags": [
"entity-resource"
]
},
"post": {
"consumes": [
"application/json"
],
"operationId": "createEntityLabel",
"parameters": [
{
"default": "16_appiniteDev",
"description": "The id of the entity to be edited",
"in": "path",
"name": "id",
"required": true,
"type": "string"
},
{
"description": "The array of labels to be set",
"in": "body",
"name": "labels",
"required": true,
"schema": {
"items": {
"type": "string"
},
"type": "array"
}
}
],
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/ResponseEntity"
}
},
"201": {
"description": "Created"
},
"401": {
"description": "Unauthorized"
},
"403": {
"description": "Forbidden"
},
"404": {
"description": "Not Found"
}
},
"summary": "Creates Labels for Entities",
"tags": [
"entity-resource"
]
}
}
}
DELETE
JAVA/SPRING
/**
* DELETE /entities/{id}/labels -> delete labels for an entity
*
* #param id
* #param labels
* #throws ServiceException
*/
#RequestMapping(value = "/entities/{id}/labels", method = RequestMethod.DELETE, produces = MediaType.APPLICATION_JSON_VALUE)
#Timed
#ApiOperation(value = "Deletes Labels for Entities", nickname = "deleteEntityLabel", consumes = "application/json")
public ResponseEntity deleteLabels(
#ApiParam(value = "The id of the entity to be edited", required = true, defaultValue = "16_appiniteDev") #PathVariable final String id,
#ApiParam(value = "The label/labels to be deleted", required = true, defaultValue = "[\"label1\",\"label2\",\"label3\"]") #NotNull final #RequestBody String[] labels
) throws ServiceException {
boolean isAppEntity = false;
User user = userService.getUserWithAuthorities();
String[] type = id.split("_");
if (StringUtils.isNumeric(type[0]) && !type[1].startsWith(type[0])) {
isAppEntity = true;
}
entityService.deleteTags(id, labels, user, isAppEntity);
Map<String, String> response = new LinkedHashMap<>();
response.put(Constants.RESPONSE_ENTITY_HEADER_MESSAGE,
"Labels deleted successfully");
return new ResponseEntity(response, HttpStatus.OK);
}
CURL FROM APP
curl 'http://localhost:8080//api/entities/52_QA42/labels?cacheBuster=1472070679337' -X DELETE -H 'Pragma: no-cache' -H 'Origin: http://localhost:8080' -H 'Accept-Encoding: gzip, deflate, sdch' -H 'Accept-Language: en-US,en;q=0.8' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36' -H 'Content-Type: text/plain;charset=UTF-8' -H 'Accept: application/json, text/plain, */*' -H 'Cache-Control: no-cache' -H 'x-auth-token: admin:1472097365429:8e6524e252e2aebb786b7738c44fe385' -H 'Referer: http://localhost:8080/' -H 'Cookie: NG_TRANSLATE_LANG_KEY=%22en%22' -H 'Connection: keep-alive' -H 'DNT: 1' --data-binary '["Bug13124"]' --compressed
CREATE
JAVA/SPRING
/**
* POST /entities/{id}/labels -> add labels for a non hadoop entity
*
* #param id
* #param labels
* #throws ServiceException
*/
#RequestMapping(value = "/entities/{id}/labels", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
#Timed
#ApiOperation(value = "Creates Labels for Entities", nickname = "createEntityLabel")
public ResponseEntity addLabels(
#ApiParam(value = "The id of the entity to be edited", required = true, defaultValue = "16_appiniteDev") #PathVariable final String id,
#ApiParam(value = "The array of labels to be set", required = true, defaultValue = "[\"label1\",\"label2\",\"label3\"]") #NotNull final #RequestBody String[] labels)
throws ServiceException {
boolean isAppEntity = false;
User user = userService.getUserWithAuthorities();
String[] type = id.split("_");
if (StringUtils.isNumeric(type[0]) && !type[1].startsWith(type[0])) {
isAppEntity = true;
}
entityService.addTags(id, labels, user, isAppEntity);
Map<String, String> response = new LinkedHashMap<>();
response.put(Constants.RESPONSE_ENTITY_HEADER_MESSAGE,
"Labels added successfully");
return new ResponseEntity(response, HttpStatus.OK);
}
CURL FROM APP
curl 'http://localhost:8080//api/entities/52_QA42/labels?cacheBuster=1472071851544' -H 'Pragma: no-cache' -H 'Origin: http://localhost:8080' -H 'Accept-Encoding: gzip, deflate' -H 'Accept-Language: en-US,en;q=0.8' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36' -H 'Content-Type: application/json;charset=UTF-8' -H 'Accept: application/json, text/plain, */*' -H 'Cache-Control: no-cache' -H 'x-auth-token: admin:1472097365429:8e6524e252e2aebb786b7738c44fe385' -H 'Referer: http://localhost:8080/' -H 'Cookie: NG_TRANSLATE_LANG_KEY=%22en%22' -H 'Connection: keep-alive' -H 'DNT: 1' --data-binary '["test"]' --compressed
Any Ideas?
I haven't been able to nail down how or where it is setting that Content-Type, so I've fixed this in a brute force way: Created an interceptor to change the header content-type by force:
.factory('contentInterceptor', function ($rootScope, $q, $location, localStorageService, $cookies) {
return {
// Add authorization token to headers
request: function (config) {
config.headers = config.headers || {};
config.headers['Content-Type'] = 'application/json';
return config;
}
};
})
.config(function ($httpProvider) {
$httpProvider.interceptors.push('contentInterceptor');
});
Works like a charm, and luckily doesn't affect any other of my API's as they ALL require Application/JSON except for the multipart form ones, but those explicitly get set and aren't affected by this interceptor.
**** UPDATE *****
I'm a dumb dumb and didn't realize I could've just put the following in my mustache template. This is the correct answer. It takes the proper 'consumes' and 'produces' properties and ensures the right headers are being sent.
{{#headers}}
options.headers['{{&name}}'] = {{&value}};
{{/headers}}

How do I transform this Paypal curl request into an ajax or angular request?

I have a Paypal request done in curl. However, I want to use AngularJS to send this request. How do I rewrite this request in AngularJS ? Or could I just use curl inside my AngularJS request ? If so, how ?
curl -v https://api.sandbox.paypal.com/v1/payments/payouts?sync_mode=true \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <Access-Token>" \
-d "{
"sender_batch_header": {
"email_subject": "You have a payment"
},
"items": [
{
"recipient_type": "EMAIL",
"amount": {
"value": 12.34,
"currency": "USD"
},
"receiver": "shirt-supplier-one#mail.com",
"note": "Payment for recent T-Shirt delivery",
"sender_item_id": "A123"
}
]
}"
Here is the link to my jsfiddle.net/dv9v4t61/4

Resources