How should a GraphQL request for file upload look like? - file-upload

I use Graphene on the server side with similar code to the one from documentation:
class UploadFile(graphene.ClientIDMutation):
class Input:
pass
# nothing needed for uploading file
# your return fields
success = graphene.String()
#classmethod
def mutate_and_get_payload(cls, root, info, **input):
# When using it in Django, context will be the request
files = info.context.FILES
# Or, if used in Flask, context will be the flask global request
# files = context.files
# do something with files
return UploadFile(success=True)
It's all clear, but how should the request look like ?
I've seen people suggesting multipart/form-data, but AFAIK that requires additional layer to parse the multipart request, so that's probably not what I need.. or is it ? :
curl -X "POST" "http://127.0.0.1:5001/graphql" \
-H 'Content-Type: multipart/form-data; boundary=----GraphQLFileUpload' \
-F "operations={\"query\":\"mutation ($files: [Upload!]!) {uploadFile(selfie: $file) {status}}\",\"variables\":{}}" \
-F "map={\"x\":[\"variables.files.x\"]}" \
-F "x=#/tmp/dummy.jpg "

I'll reply myself. The curl code I had was based on an external library that confused the hell out of me.
Here's my solution that doesn't require any additional library:
Python server code (graphene):
class UploadImage(graphene.Mutation):
class Arguments(object):
file = graphene.String(required=True)
status = graphene.Boolean()
def mutate(self, info, file):
img = info.context.files[file].read()
# more stuff
return UploadImage(status=True)
Curl request (multipart form)
curl -X POST http://localhost:5001/graphql \
-H 'content-type: multipart/form-data; boundary=----GraphQlFileUpload' \
-F 'query=mutation {uploadImage(file: "photo") {status}}' \
-F 'photo=#selfie.jpg'

Related

Python requests return empty response after file upload

I want to upload a file via Python requests. I have successful tries with Postman and Curl. On successful response, I get the file id, but using requests i get status code 200 and empty json.
Curl example:
curl --location --request POST 'http://someurl.com/api/file' \
--header 'Content-Type: multipart/form-data' \
--header 'Accept: application/json' \
--header 'Authorization: Basic TWFsZWtzZXkubHVraW55a2hfdGVzdDE6UWF6MVdzeEA=' \
--form 'file=#"1.png"' \
--form 'fileName="1.png"' \
--form 'fileType="image/png"'
Curl output:
{
"fileId": 328446
}
Python requests:
import requests
session = requests.session()
files = {'file': ('1.png', open('1.png', 'rb'), 'image/png',)}
response = session.post('http://someurl.com/api/file', auth=HTTPBasicAuth('my_login', 'my_password'), files=files)
print(response.json())
requests output:
{}
I also tried to attach a file through this topic, but the version of the requests is older there
Python requests doesn't upload file
Postman form-data example
API POST request Example
Found a solution. This code works
import requests
from requests.auth import HTTPBasicAuth
url = 'http://someurl.com/api/file'
payload={'fileName': '1.png', 'fileType': 'image/png'}
files= {'file': open('1.png','rb')}
response = requests.post(url, auth=HTTPBasicAuth('my_login', 'my_password'), data=payload, files=files)
print(response.json())

How to get the stock option train data with tda-api?

I have registered a tdameritrade developer account and got a api key.
curl -X GET --header "Authorization: " \
"https://api.tdameritrade.com/v1/marketdata/aapl/quotes?apikey=my_tda_api_key"
It can get aapl's data such as below:
{"AAPL": {"assetType":"EQUITY","assetMainType":"EQUITY","cusip":"037833100","symbol":"AAPL",
#omitted all other info
Now i want to get aapl's stock option train with curl and my api key:
curl -X GET --header "Authorization: " "https://api.tdameritrade.com/v1/marketdata/chains? \
apikey=my_tda_api_key& \
symbol=aapl&contractType=all&includeQuotes=false&strategy=single&interval=1&range=all& \
fromDate=2021-8-14&toDate=2023-8-14&expMonth=all&optionType=all"
I always get all HTTP/1.1 400 Bad Request ,tried many different arguments combination in the url ,still can't get normal response,how to fix then?
https://developer.tdameritrade.com/option-chains/apis/get/marketdata/chains#
import requests
import json
td_consumer_key = "xxxxxxxxxxxxxxxxxxxxxx"
base_url = 'https://api.tdameritrade.com/v1/marketdata/chains?\
&symbol={stock_ticker}&contractType={contract_type}\
&strike={strike}&fromDate={date}&toDate={date}'
endpoint = base_url.format(stock_ticker = 'AAPL',
contract_type = 'PUT',
strike = 125,
date='2021-08-27')
page = requests.get(url=endpoint,
params={'apikey' : td_consumer_key})
content = json.loads(page.content)

Is it possible to use curl/json with tcl and retrieve spotify API data?

I'm trying to make a simple proc in TCL that gets data from SPOTIFY API about what track I'm currently playing.
Any ideas are welcome. :D
Format:
GET https://api.spotify.com/v1/me/player/currently-playing
I need to send this:
curl -X "GET" "https://api.spotify.com/v1/me/player/currently-playing?market=ES&additional_types=episode" -H "Accept: application/json" -H "Content-Type: application/json" -H "Authorization: Bearer BQAai*****8n-5zXrLypj********hsgafd"
(id code for auth masked)
Reference: https://developer.spotify.com/documentation/web-api/reference/
This is a variant of Donald's solution using Tcl's built-in http support:
package require http;
package require json;
package require tls
::http::register https 443 ::tls::socket
set spotifyToken "BQAai*****8n-5zXrLypj********hsgafd"
proc spotifyGet {api args} {
global spotifyToken;
set url https://api.spotify.com/v1/$api?[http::formatQuery {*}$args]
dict set hdrs Authorization [list Bearer $spotifyToken]
dict set hdrs Accept "application/json"
set token [http::geturl $url \
-type "application/json" \
-headers $hdrs]
if {[http::status $token] eq "ok"} {
set responseBody [http::data $token]
} else {
error "Spotify call failed: [http::error $token]"
}
http::cleanup $token
return [json::json2dict $responseBody]
}
set data [spotifyGet me/player/currently-playing market ES additional_types episode]
Not so complicated, after all, but requires an additional dependency: TclTLS.
As a first cut, here's a very simple wrapper:
proc curl args {
# The options skip showing stuff you don't want in scripted form
# They also enable following redirects; you probably want to do that!
exec curl -s -S -L {*}$args
}
# Usually easiest to keep this sort of thing separate
set spotifyToken "BQAai*****8n-5zXrLypj********hsgafd"
# -G to force the use of the GET verb
set json [curl -G "https://api.spotify.com/v1/me/player/currently-playing?market=ES&additional_types=episode" -H "Accept: application/json" -H "Content-Type: application/json" -H "Authorization: Bearer $spotifyToken"]
We can wrap that further:
package require http; # Standard part of Tcl
package require json; # Part of tcllib
proc spotifyGet {api args} {
global spotifyToken; # Assume variable set as earlier
set url https://api.spotify.com/v1/$api?[http::formatQuery {*}$args]
set options {-H "Accept: application/json" -H "Content-Type: application/json"}
lappend options -H "Authorization: Bearer $spotifyToken"
return [json::json2dict [curl -G $url {*}$options]]
}
set data [spotifyGet me/player/currently-playing market ES additional_types episode]
puts [dict get $data item name]
If you're doing more serious JSON work, consider using the rl_json library. And you'll need to explore the data you get back to understand it. (I can't test; I don't use Spotify.)

Segment.io HTTP API not collecting events

The documentation and help for this particular Segment.io is limited and sparse, so I hope it's OK to ask in here.
I have just set up a Segment.io workspace and a HTTP API source
Per the docs, I sent some POST requests (with Postman) to the https://api.segment.io/v1/track and https://api.segment.io/v1/page endpoints. The requests were structured like this:
curl -X POST \
https://api.segment.io/v1/track \
-H 'Accept: */*' \
-H 'Authorization: My4w3s0m3k3y' \
-H 'Cache-Control: no-cache' \
-H 'Connection: keep-alive' \
-H 'Content-Type: application/json' \
-H 'Host: api.segment.io' \
-H 'Postman-Token: 474d7fbe-15af-43d2-b629-61e15945e662,2c3d5fbe-2c09-4fe6-b7ea-a04e3221201b' \
-H 'User-Agent: PostmanRuntime/7.11.0' \
-H 'accept-encoding: gzip, deflate' \
-H 'cache-control: no-cache' \
-H 'content-length: 117' \
-d '{
"userId": "abc123",
"event": "My tests",
"properties": {
"name": "test 1"
}
}'
which all returned a 200 response and the following message:
{
"success": true
}
However, when I got to my dashboard, no events have been recorded.
The debugger is also empty
What am I missing here?
It looks like your write key isn't base64 encoded. When you encode your write key, remember to add the : at the end of it, before it's encoded.
Also, for the Authorization key:value, be sure to add Basic before the encoded write key. So your Authorization key:value would look like:
Authorization: Basic {encoded write key}
An example from the segment documentation:
In practice that means taking a Segment source Write Key,'abc123', as the username, adding a colon, and then the password field is left empty. After base64 encoding 'abc123:' becomes 'YWJjMTIzOg=='; and this is passed in the authorization header like so: 'Authorization: Basic YWJjMTIzOg=='.
I have been dealing with the same issue.
I found the solution as Todd said.
You should add a header Authorization: Basic + base64 encoding write key.
So, you look for the Segment source setting and get the write key.
After that, i have used an online base64 encoding tool to encode my write key.
Finally, you should add this header (Authorization) with 'Basic' and the encoded write key.
You should be able to see the tracked event in the Debugging panel in Segment web page.
I hope this helps!
You can try this code
const { promisify } = require("util");
var Analytics = require("analytics-node");
var analytics = new Analytics("xxxxxxxxxxxxxxxxxxxxxxx", {
flushAt: 1,
});
const [identify, track] = [
analytics.identify.bind(analytics),
analytics.track.bind(analytics),
].map(promisify);
console.log("user id: ", req.body.event.app_user_id);
let app_user_id = req.body.event.app_user_id;
let period_type = req.body.event.period_type;
let expiration_at_ms = req.body.event.expiration_at_ms;
let ret = "Initial";
try {
await identify({
userId: app_user_id,
traits: {
period_type: period_type,
expiration_at_ms: expiration_at_ms,
},
});
ret = "Done : Sengment done";
} catch (err) {
console.log("err: ", err);
ret = "Error : " + err;
}
return {
rafsan: ret,
};
Try to clear your browser's cache or use a different browser. I had the same problem and worked for me.
Hope this helps.

PUT requests to upload a file in form data Using karate

I've tried to write equivalent karate script for below curl request
curl -X PUT \
'http://localhost:8055/uploadfile' \
-H 'content-type: multipart/form-data;' \
-F code=#/Users/test/Downloads/Next.zip
Tried karate script
Given path 'uploadfile'
#Given header Content-Type = 'multipart/form-data'
And form field code = '/Users/test/Downloads/Next.zip'
#And multipart file code = { read: '/Users/test/Downloads/Next.zip' , contentType: 'application/zip' }
When method PUT
Then status 200
Am I doing something mistake here (tried different things)? Still not getting expected API response.
FYI : I've got that curl command from postman and it is working fine.
It is hard to tell with the limited info you have provided. Try this:
Given url 'http://localhost:8055/uploadfile'
And multipart file code = { read: 'file:/Users/test/Downloads/Next.zip', filename: 'Next.zip', contentType: 'application/zip' }
When method put
If you are still stuck follow this process: https://github.com/intuit/karate/wiki/How-to-Submit-an-Issue (or use postman ;)