Reqwest's Client.post() returning 400 bad request for File.io API - rust

I'm learning Rust, and thought it would be handy to build a CLI to share files with the File.io API.
To do so, I am trying to use reqwest to send a request as described in the File.io docs:
# from file.io doc -> works fine
$ curl --data "text=this is a secret pw" https://file.io
> {"success":true,"key":"zX0Vko","link":"https://file.io/zX0Vko","expiry":"14 days"}
When I run the below code, I get a 400 response. Perhaps there's an issue with the headers? I've tried looking at the curl docs to find out what I could be missing, but I'm stumped.
Any help would be appreciated.
My code:
extern crate reqwest;
fn main() {
let client = reqwest::Client::new();
let res = client.post("https://file.io/")
.body("text=this is a practice run")
.send();
println!("{:?}", res);
}
Expected Response:
{"success":true,"key":"SOME_KEY","link":"SOME_LINK","expiry":"14 days"}
Actual Response:
Ok(Response { url: "https://file.io/", status: 400, headers: {"date": "Wed, 06 Feb 2019 03:40:35 GMT", "content-type": "application/json; charset=utf-8", "content-length": "64", "connection": "keep-alive", "x-powered-by": "Express", "x-ratelimit-limit": "5", "x-ratelimit-remaining": "4", "access-control-allow-origin": "*", "access-control-allow-headers": "Cache-Control,X-reqed-With,x-requested-with", "etag": "W/\"40-SEaBd3tIA9c06hg3p17dhWTvFz0\""} })

Your requests are not equivalent. curl --data means you're trying to send a HTML form with content type "x-www-form-urlencoded" or similar, whereas this line in your code
.body("text=this is a practice run")
means "just a text". You should use ReqwestBuilder::form as described here

Related

FastApi and HTTP header Authorization: Token, get error in use "authorization: token is an invalid header name"

I need use HTTP authorization with header Authorization: Token. My code:
#router.get('/versions',tags=["Credentials"],responses={
200: {
"model": List[models.versions_info],
"description": "Return has code",
"headers": {"Authorization": {"description":"Token party","type":"string"}}
}})
async def list_versions(token: Union[str, None] = Header(description="Token party",alias="Authorization: Token",default=None)):
out=[{"version": "2.1.1","url": "https://www.server.com/ocpi/2.1.1/"},{"version": "2.2","url": "https://www.server.com/ocpi/2.2/"}]
return Response(status_code=200,content=json.dumps(out), media_type="application/json", headers={"Authorization: Token "+config.globals["mytoken"]})
However, when using I get an error:
Can you tell me where I'm wrong?
Update: if i modify code to:
async def list_versions(token: Union[str, None] = Header(alias="Authorization",default=None))
the header is not sent at all:

Reqwest May Not Be Detecting My URL, Request Not Sending Request

reqwest gives me the following error when trying to send a post request:
Error: Response { url: Url { scheme: "https", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("eastus.tts.speech.microsoft.com")), port: None, path: "/cognitiveservices/v1", query: None, fragment: None }, status: 400, headers: {"date": "Thu, 18 Aug 2022 21:48:56 GMT", "transfer-encoding": "chunked", "connection": "keep-alive", "strict-transport-security": "max-age=15724800; includeSubDomains"} }
With the following code:
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let url: String = "https://eastus.tts.speech.microsoft.com/cognitiveservices/v1".to_string();
let body: String = format!(r#"
<speak version='\''1.0'\'' xml:lang='\''en-US'\''>
<voice xml:lang='\''en-US'\'' xml:gender='\''Female'\'' name='\''en-US-SaraNeural'\''>
my voice is my passport verify me
</voice>
</speak>
"#);
let res = Client::new()
.post(url)
.header( "Ocp-Apim-Subscription-Key", "mySecretKeyIAmWritingThisHereForSecurity")
.header(CONTENT_TYPE, "application/ssml+xml")
.header("X-Microsoft-OutputFormat","audio-16khz-128kbitrate-mono-mp3")
.header(USER_AGENT, "curl")
.body(body)
.send().await?;
println!("Status Code: {:?}", res.status());
Ok(())
}
It is weird because it says cannot_be_a_base: false, username: "" but I don't need/have such things... also, this data being sent to Azure works if sent via the command line with CURL.
What I am trying to achieve, my situation:
curl --location --request POST "https://eastus.tts.speech.microsoft.com/cognitiveservices/v1" \
--header "Ocp-Apim-Subscription-Key: myKEYgoesHERE" \
--header 'Content-Type: application/ssml+xml' \
--header 'X-Microsoft-OutputFormat: audio-16khz-128kbitrate-mono-mp3' \
--header 'User-Agent: curl' \
--data-raw '<speak version='\''1.0'\'' xml:lang='\''en-US'\''>
<voice xml:lang='\''en-US'\'' xml:gender='\''Female'\'' name='\''en-US-SaraNeural'\''>
stop it
</voice>
</speak>' > output.mp3
I wanna turn that curl into a rust reqwest... so
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let url: String = "https://eastus.tts.speech.microsoft.com/cognitiveservices/v1".to_string();
let body: String = format!(r#"
<speak version='\''1.0'\'' xml:lang='\''en-US'\''>
<voice xml:lang='\''en-US'\'' xml:gender='\''Female'\'' name='\''en-US-SaraNeural'\''>
my voice is my passport verify me
</voice>
</speak>
"#);
let res = Client::new()
.post(url)
.header( "Ocp-Apim-Subscription-Key", "MYkey")
.header(CONTENT_TYPE, "application/ssml+xml")
.header("X-Microsoft-OutputFormat","audio-16khz-128kbitrate-mono-mp3")
.header(USER_AGENT, "curl")
.body(body)
.send().await?;
println!("OOO {:?}", res);
Ok(())
}
I believe I am missing maybe the --location flag here yet I do not believe that is the issue
You are using the same string escape syntax that you used in the curl example, but Rust and shell strings are different things, different syntax. The end result of the curl command is that each '\'' simply encodes a single '. You don't need to escape 's in a Rust raw literal like r#""#, just include them directly as you want it sent:
let body = format!(r#"
<speak version='1.0' xml:lang='en-US'>
<voice xml:lang='en-US' xml:gender='Female' name='en-US-SaraNeural'>
my voice is my passport verify me
</voice>
</speak>
"#);

Influxdb2 Python API: Path not found

I have a working InfluxDb2 server and, on a Raspberry Pi, the Python client library.
I've generated the the tokens in the server UI and copied an all-areas one into the Python. The test bucket is set up in the UI too. In the Python program I have this:
bucket = "test"
org = "test-org"
#
token = "blabla=="
# Store the URL of your InfluxDB instance
url="http://10.0.1.1:8086/api/v2"
client = influxdb_client.InfluxDBClient(
url=url,
token=token,
org=org
)
Followed later by:
p = influxdb_client.Point("my_measurement").tag("location", "Prague").field("temperature", 25.3)
write_api = client.write_api(write_options=SYNCHRONOUS)
write_api.write(bucket='test', org='test-org', record=p)
I've overcome the not-authorized but now, whatever I do, I end up with this:
influxdb_client.rest.ApiException: (404)
Reason: Not Found
HTTP response headers: HTTPHeaderDict({'Content-Type': 'application/json; charset=utf-8', 'X-Influxdb-Build': 'OSS', 'X-Influxdb-Version': 'v2.2.0', 'X-Platform-Error-Code': 'not found', 'Date': 'Tue, 26 Apr 2022 14:35:50 GMT', 'Content-Length': '54'})
HTTP response body: {
"code": "not found",
"message": "path not found"
}
I've also gone back to Curl which gives me not authorized problem with the same parameters. Any help appreciated, beginning to regret trying to upgrade now.
You don't need the /api/v2 in your url parameter, just url="http://10.0.1.1:8086"
See https://github.com/influxdata/influxdb-client-python#getting-started

Convert curl command into a working script

I am using an API from check-host.net to ping an website.
My issue is right now that I have no ideea how I could transform the curl command api into an working python script. I tried different approaches which I found on here but sadly none has give me the ouput I am looking for.
Working curl command:
curl -H "Accept: application/json" \ https://check-host.net/check-tcp?host=smtp://gmail.com&max_nodes=1
the respons looks something like that:
{ "ok": 1, "request_id": "29", "permanent_link":
"https://check-host.net/check-report/29", "nodes": {
"7f000001": ["it","Italy", "Marco"] } }
You have to send a Accept: application/json header in your request. You can also use the builtin json decoder in requests.
import requests
headers={
'Accept': 'application/json'
}
r=requests.get('https://check-host.net/check-tcp?host=smtp://gmail.com&max_nodes=1',headers=headers)
print(r.json())
Output
{'nodes': {'us2.node.check-host.net': ['us', 'USA', 'New Jersey', '199.38.245.218', 'AS394625', 'OK']}, 'ok': 1, 'permanent_link': 'https://check-host.net/check-report/a462c3ck399', 'request_id': 'a462c3ck399'}

Nodejs app using Mailjet throwing a confusing error

I'm building an app using Mailjet, and using their connection example.
app.get('/send',function(req,res){
...
var request = mailjet
.post("send")
.request({
<request stuff, email details>
});
request
.on('success', function (response, body) {
<handle response>
})
.on('error', function (err, response) {
<handle error>
});
Getting this error:
Unhandled rejection Error: Unsuccessful
at /home/ubuntu/workspace/node_modules/node-mailjet/mailjet-client.js:203:23
When I go to the Mailjet client and ask it to log the error, it tells me:
{ [Error: Unauthorized]
original: null,
...
Anyone have an idea of where I should start troubleshooting?
Update: saw this in the error output:
header:
{ server: 'nginx',
date: 'Thu, 02 Mar 2017 14:04:11 GMT',
'content-type': 'text/html',
'content-length': '20',
connection: 'close',
'www-authenticate': 'Basic realm="Provide an apiKey and secretKey"',
vary: 'Accept-Encoding',
'content-encoding': 'gzip' },
So it's not eating my API key and secret. Can anyone tell me how to set those as environmental variables in Cloud9?
You can set environment variables in ~/.profile. Files outside of the workspace directory /home/ubuntu/workspace aren't accessible for read-only users so people won't be able to see them.
In the terminal, you can do for example:
$> echo "export MAILJET_PUBLIC=foo" >> ~/.profile
$> echo "export MAILJET_SECRET=bar" >> ~/.profile
Then, you'll be able to access those variables in Node when using the connect method:
const mailjet = require ('node-mailjet')
.connect(process.env.MAILJET_PUBLIC, process.env.MAILJET_SECRET)
The runners (from the "run" button) and the terminal will evaluate ~/.profile and make the environment variable available to your app.

Resources