Sending Array of string in grape API - ruby

Using grape api, I try to send an array of string but I always have the response error, codes is not valid
In my model, I expose my field like this :
expose :code, documentation: { type: Array[String]}
And when I make my test, I pass
"code": [
"037ffdb5-6901-404c-b152-8321a32aa397", "1762005c-8cf0-427d-b090-d354d6255eba"
],
When I check in my console, I have an array of string passed in my params :
=> ["037ffdb5-6901-404c-b152-8321a32aa397", "1762005c-8cf0-427d-b090-d354d6255eba"]
Is anyone having a clue why my params are not valid ?

Related

What is the most elegant way in Golang to create JSON-RPC struct with params

I'm creating a Golang app to communicate with proprietary third-party JSON-RPC API that is sensitive to the order of elements.
Request should be sent using POST over HTTPS. Here is a request sample:
{
"jsonrpc": "2.0",
"method": "ab_123",
"params": [
"ee0fe150-6648-11ed-bd23-c1392b9c96ae",
"test#example.com",
"NONE"
]
}
In API docs it's documented that first param should be id, second param is email and third param is name. There are may be dozens of params, some of them are optional (can have value NONE).
I'm looking for the most elegant way to create the request struct that will be readable and easy maintainable.
Here is what I have so far:
type APIRequest struct {
Jsonrpc string `json:"jsonrpc"`
Method string `json:"method"`
Params []string `json:"params"`
}
var request = APIRequest{
Jsonrpc: "2.0",
Method: "ab_123",
Params: []string{
"ee0fe150-6648-11ed-bd23-c1392b9c96ae",
"test#example.com",
"NONE",
},
}

Get complete GraphQL response using POST without specify field name in request [duplicate]

Assume you have a GraphQL type and it includes many fields.
How to query all the fields without writing down a long query that includes the names of all the fields?
For example, If I have these fields :
public function fields()
{
return [
'id' => [
'type' => Type::nonNull(Type::string()),
'description' => 'The id of the user'
],
'username' => [
'type' => Type::string(),
'description' => 'The email of user'
],
'count' => [
'type' => Type::int(),
'description' => 'login count for the user'
]
];
}
To query all the fields usually the query is something like this:
FetchUsers{users(id:"2"){id,username,count}}
But I want a way to have the same results without writing all the fields, something like this:
FetchUsers{users(id:"2"){*}}
//or
FetchUsers{users(id:"2")}
Is there a way to do this in GraphQL ??
I'm using Folkloreatelier/laravel-graphql library.
Unfortunately what you'd like to do is not possible. GraphQL requires you to be explicit about specifying which fields you would like returned from your query.
Yes, you can do this using introspection. Make a GraphQL query like (for type UserType)
{
__type(name:"UserType") {
fields {
name
description
}
}
}
and you'll get a response like (actual field names will depend on your actual schema/type definition)
{
"data": {
"__type": {
"fields": [
{
"name": "id",
"description": ""
},
{
"name": "username",
"description": "Required. 150 characters or fewer. Letters, digits, and #/./+/-/_ only."
},
{
"name": "firstName",
"description": ""
},
{
"name": "lastName",
"description": ""
},
{
"name": "email",
"description": ""
},
( etc. etc. ...)
]
}
}
}
You can then read this list of fields in your client and dynamically build a second GraphQL query to get the values of these fields.
This relies on you knowing the name of the type that you want to get the fields for -- if you don't know the type, you could get all the types and fields together using introspection like
{
__schema {
types {
name
fields {
name
description
}
}
}
}
NOTE: This is the over-the-wire GraphQL data -- you're on your own to figure out how to read and write with your actual client. Your GraphQL javascript library may already employ introspection in some capacity. For example, the apollo codegen command uses introspection to generate types.
2022 Update
Since this answer was originally written, it is now a recommended security practice to TURN OFF introspection in production. Reference: Why you should disable GraphQL introspection in production.
For an environment where introspection is off in production, you could use it in development as a way to assist in creating a static query that was used in production; you wouldn't actually be able to create a query dynamically in production.
I guess the only way to do this is by utilizing reusable fragments:
fragment UserFragment on Users {
id
username
count
}
FetchUsers {
users(id: "2") {
...UserFragment
}
}
I faced this same issue when I needed to load location data that I had serialized into the database from the google places API. Generally I would want the whole thing so it works with maps but I didn't want to have to specify all of the fields every time.
I was working in Ruby so I can't give you the PHP implementation but the principle should be the same.
I defined a custom scalar type called JSON which just returns a literal JSON object.
The ruby implementation was like so (using graphql-ruby)
module Graph
module Types
JsonType = GraphQL::ScalarType.define do
name "JSON"
coerce_input -> (x) { x }
coerce_result -> (x) { x }
end
end
end
Then I used it for our objects like so
field :location, Types::JsonType
I would use this very sparingly though, using it only where you know you always need the whole JSON object (as I did in my case). Otherwise it is defeating the object of GraphQL more generally speaking.
GraphQL query format was designed in order to allow:
Both query and result shape be exactly the same.
The server knows exactly the requested fields, thus the client downloads only essential data.
However, according to GraphQL documentation, you may create fragments in order to make selection sets more reusable:
# Only most used selection properties
fragment UserDetails on User {
id,
username
}
Then you could query all user details by:
FetchUsers {
users() {
...UserDetails
}
}
You can also add additional fields alongside your fragment:
FetchUserById($id: ID!) {
users(id: $id) {
...UserDetails
count
}
}
Package graphql-type-json supports custom-scalars type JSON.
Use it can show all the field of your json objects.
Here is the link of the example in ApolloGraphql Server.
https://www.apollographql.com/docs/apollo-server/schema/scalars-enums/#custom-scalars

Querydict not recognizing json array in django

Django and Django Rest Framework is not sensing the array in the following JSON object:
{
"datum":
[
{'proposed':'20/sep/2018', "pk":"475"},
{'proposed':'20/sep/2018', "pk":"517"}
]
}
When I do a print(request.data) this is the output:
<QueryDict: {'{"datum":[{"proposed_submission_date":"20/Sep/2018","pk":"475"},{"proposed_submission_date":"20/Sep/2018","pk":"512"}]}': ['']}>
and when I do a print(request.data.keys())I get:
{"datum":[{"proposed_submission_date":"20/Sep/2018","pk":"475"},{"proposed_submission_date":"20/Sep/2018","pk":"512"}]}
You can see that its taking the json string as the key, and not assigning "datum" as the key.
Do I need to do something else with the JSON string?
I'm doing an AJAX PUT to the Django rest framework backend.
the fact that you see a QueryDict rather than just a dict is a sign that you sent your data as application/x-www-form-urlencoded or multipart/form-data.
Ensure you send the request with a application/json content type and it should be just fine.

Why is an Array in my payload being flattened in Sinatra / Rack::Test?

I'm trying to test a small Sinatra app using rspec. I want to pass a rather complex payload and am running into issues i do not understand: my payload contains an array of hashes. When I run the actual application this will work as expected, yet when I use the post helper to run my tests, the array will contain a merged hash:
post(
"/#{bot}/webhook",
sessionId: "test-session-#{session_counter}",
result: {
contexts: [
{ some: 'fixture' },
{ name: 'generic', parameters: { facebook_sender_id: 'zuck-so-cool' } }
]
}
)
In the sinatra handler I use params to access this payload:
post '/:bot/webhook' do |bot|
do_something_with(params)
end
When I now look at the structure of params when running the test suite, I will see the following structure:
[{"some" => "fixture", "name" => "generic", "parameters" => {"facebook_sender_id" => "zuck-so-cool"}}]
which I do not really understand. Is this a syntax issue (me being a ruby noob), am I using params wrong, or is this a bug?
EDIT: So i found out this is an "issue" with the way that Rack::Test will serialize the given payload when not specifying how to (i.e. as form data). If I pass JSON and pass the correct headers it will do what I expect it to do:
post(
"/#{bot}/webhook",
{
sessionId: "test-session-#{session_counter}",
result: {
contexts: [
{ some: 'fixture' },
{ name: 'generic', parameters: { facebook_sender_id: 'zuck-so-cool' } }
]
}
}.to_json,
{ 'HTTP_ACCEPT' => 'application/json', 'CONTENT_TYPE' => 'application/json' }
)
Still I am unsure of this is an issue with the passed data structure not being possible to be serialized into form data or if this is a bug in the way that Rack::Test serializes data.
Looking at the relevant portion of the specs it looks like this is is expected behavior.

How to do POST request to Grape REST API using params block compatible with Swagger

I am using grape to build a REST API, I am having some trouble with params options.
This is how I do a POST request:
# Curl Request
# curl -X POST -H "Content-Type:application/json" 0:9292/v1/articles -d '{"title":"hello","body":"world"}'
# {"error":"article is missing"}
# curl -X POST -H "Content-Type:application/json" 0:9292/v1/articles -d '{"article":{title":"hello","body":"world"}}'
# {"error":"article is invalid"}
As you can see if I omit article it fails article missing, If i put article and it fails article invalid.
This is the code, I am using grape-entity.
# Entity
module API
module Entities
class Article < Grape::Entity
expose :title, documentation: { type: 'string', desc: 'Title' }
expose :body, documentation: { type: 'string', desc: 'Body' }
end
end
end
# API
desc "Create an article"
params do
requires :article, type: API::Entities::Article, documentation: { eg: "aklsdfj" }
end
post '/articles' do
puts params
article = Article.create(params(:title, :body))
represent(article, env)
end
# Add Swagger Docs
add_swagger_documentation mount_path: 'api/doc',
api_version: 'v1',
markdown: GrapeSwagger::Markdown::KramdownAdapter,
hide_documentation_path: true,
base_path: Application.config.base_path,
models: [API::Entities::Article]
Specifically the problem is caused by params block, it requires an :article of type API:Entities::Article.
Also note that, I am using add-swagger-documentation, and this code
produces correct swagger documentation, so the solution have to be
fully compatible with swagger. What is the correct usage of params
block without offending the swagger.
I'm not sure what you're trying to accomplish here. I guess you want to change your post method in a way that it accepts a JSON like this:
{ attribute1: value, attribute2: value }
instead of
{ article: { attribute1: value, attribute2: value } }
In this case, you have to change your params block to something like this
params do
requires :attribute1, type: String, documentation: { eg: "aklsdfj" }
requires :attribute2, type: String, documentation: { eg: "aklsdfj" }
end
instead of
params do
requires :article, type: API::Entities::Article, documentation: { eg: "aklsdfj" }
end
The params block above is expecting a JSON containing an article attribute composed by every attribute defined in the entity API::Entities::Article.
In fact, Grape doesn't accept entity objects as a type for a parameter.

Resources