Microsoft Bot Framework (WebChat) - 500 Internal Server Error - botframework

From "Test in Web Chat" window in Azure Dashboard, I entered "hello" which is correctly received in my backend, but I'm still figuring out how to reply.
Note: WORDS IN CAPS means variable.
curl -d "grant_type=client_credentials&client_id=CLI-ENT-ID&client_secret=SECRET&scope=https%3A%2F%2Fapi.botframework.com%2F.default" -X POST https://login.microsoftonline.com/botframework.com/oauth2/v2.0/token
Response: {"token_type":"Bearer","expires_in":3600,"ext_expires_in":0,"access_token":"VERY_LONG_STRING"}
curl -d '{"type":"message","from":{"id":"mybot#SOME_ID","name":"mybot"},"conversation":{"id":"CONVERSATION_ID"},"recipient":{"id":"RECIPIENT_ID","name":"You"},"locale":"en","text":"hello too","replyToId":"CONVERSATION_ID|0000008"}' -H "Content-Type: application/json" -H "Authorization: Bearer VERY_LONG_STRING" -X POST https://api.botframework.com/v3/conversations/CONVERSATION_ID/activities/CONVERSATION_ID%7C0000008
Response: The page cannot be displayed because an internal server error has occurred.
Request from my app (also same error):
POST /v3/conversations/CONVERSATION_ID/activities/CONVERSATION_ID%7C0000008 HTTP/1.1
Accept: application/json
Content-Type: application/json
Authorization: Bearer VERY_LONG_STRING
User-Agent: Java-SDK
Content-Length: 273
Host: api.botframework.com
Connection: Keep-Alive
Accept-Encoding: gzip,deflate
{"type":"message","from":{"id":"mybot#SOME_ID","name":"mybot"},"conversation":{"id":"CONVERSATION_ID"},"recipient":{"id":"RECIPIENT_ID","name":"You"},"locale":"en","text":"hello too","replyToId":"CONVERSATION_ID|0000008"}
What do I miss?

Thanks to comment from Eric Dahlvang, I figure it out.
By default, ApiClient generated from swagger will have its basePath hardcoded to https://api.botframework.com.
Before replying, take the serviceUrl from incoming Activity and use it to change the basePath.

Related

Adapt multipart/form-data request to curl with image and json in the same request

I need to rewrite this curl request extracted from the browser to execute it from bash, it is a multipart/form-data that combines the upload of an image together with a json in the same request, I have carried out several tests substituting the raw data for two -F but the server responds with error.
What would be the correct way?
I also fail to understand the key that is next to WebKitFormBoundary is a value that seems random, is it just a separator? can i use anything?
I have removed the headers that I considered irrelevant
curl 'https://localhost' \
-H 'Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryXXXXXXXXXXXXXXXX'
-H 'Accept: */*' \
--data-raw $'------WebKitFormBoundaryXXXXXXXXXXXXXXXX\r\nContent-Disposition: form-data; name="image"; filename="image.jpg"\r\nContent-Type: image/jpeg\r\n\r\n\r\n------WebKitFormBoundaryXXXXXXXXXXXXXXXX\r\nContent-Disposition: form-data; name="item"; filename="blob"\r\nContent-Type: application/json\r\n\r\n{"item1":"xxxx","item2":"yyyy"}\r\n------WebKitFormBoundaryXXXXXXXXXXXXXXXX--\r\n' \
Thanks
I also fail to understand the key that is next to WebKitFormBoundary is a value that seems random, is it just a separator? can i use anything?
yes and yes and practically speaking yes. it's supposed to be a random-guaranteed-unique string used as separator to signal start and end of forms.. if you know beforehand that none of your uploads contains the string stackoverflow, you could use Content-Type: multipart/form-data; boundary=stackoverflow for example (but this may break if you upload a file actually containing the string stackoverflow !), but you should let curl generate that string automatically, rather than specifying it yourself, curl will auto-generate a string that is practically guaranteed to be unique.
I have removed the headers that I considered irrelevant
... if you guessed wrong, the server may give you an error for missing a required header. assuimg that you didn't make any mistakes in removing irrelevant headers though, i think it's
curl 'https://localhost'\
--form "image=#image.jpg;type=image/jpeg"\
--form "item=#blob;type=application/json"
the request generated by that command is roghly:
POST / HTTP/1.1
Host: localhost
User-Agent: curl/7.81.0
Accept: */*
Content-Length: 359
Content-Type: multipart/form-data; boundary=------------------------7d0262831ce8f248
--------------------------7d0262831ce8f248
Content-Disposition: form-data; name="image"; filename="image.jpg"
Content-Type: image/jpeg
image.jpg content
--------------------------7d0262831ce8f248
Content-Disposition: form-data; name="item"; filename="blob"
Content-Type: application/json
["json lol"]
--------------------------7d0262831ce8f248--
as you can see above, Accept: */* is curl's default accept-header anyway, so there's no need to specify it, and curl auto-generated the boundary ------------------------7d0262831ce8f248 so there's no need to manually specify a boundary either.

Can't send a Jmeter request with graphql, 400 response using valid URL

From what I've read on https://graphql.org/learn/serving-over-http/ and Performance test for graphQL API, I can send a graphQL request over jmeter.
In the stack overflow example, a graphQL server was built with Apollo and then queried via Jmeter. I am just trying to do load testing and not build schemas or data sets, so I don't have Apollo on my local machine, and I'm also not sure that I would be testing the QA environment if I did try to do this all locally.
I can access our graphQL at https://proprietary-website/graphql/gql and if I run the following query, it returns the expected results:
query currentUserProfile {
currentUserProfile {
id
}
}
Now, I try to apply that to jmeter
I create a HTTP Request in my thread group with protocol: https, server name: proprietary-website, method: GET, path: /graphql/gql
I create an HTTP Header Manager and include the required Bearer Token and Content-Type headers
I create a listener to View Results Tree
Then I run a jmeter load test with 500 threads
I see the valid URL passed in the request body:
GET https://proprietary-website/graphql/gql
GET data:
{"query":{"currentUserProfile {id}"}}
[no cookies]
but I get back:
HTTP/1.0 400 Bad Request
Content-Type: text/html; charset=UTF-8
Referrer-Policy: no-referrer
Content-Length: 1555
Date: Thu, 12 Dec 2019 16:40:26 GMT
I am new to graphql, am I not allowed to send Jmeter requests to the URL my dev gave me and do I have to use the apollo server? If so, can someone point me to some examples?
I am on Windows 10
I also tried:
k6, but this requires docker and i have no admin rights on my computer
easygraphql-lt but when I ran a test script with #easygraphql-lt, I got dependency errors that I don't quite understand how to fix
I looked at easygraphql-load-tester, but this would require me to have access to the project but all i have is the website. I don't have a graphQL.js or an index.js to reference
UPDATE: I just saw that I can copy the query as a curl request so I pasted that request in command line and it gave me extra headers that I put in my jmeter HTTP Header manager:
$ curl 'https://proprietary-website/graphql/gql' -H 'Accept-Encoding: gzip, deflate, br' -H 'Content-Type: application/json' -H 'Accept: application/json' -H 'Connection: keep-alive' -H 'DNT: 1' -H 'Origin: https://proprietary-website' -H 'Authorization: Bearer redacted' --data-binary '{"query":" query currentUserProfile { currentUserProfile { id }}"}'
But I still get a 400 back, so I think I need to send the query differently as it is showing appended as a --data-binary (not sure what that means). I tried some other SO suggestions, no luck so far
I also tried against an app out of the O'Reilly graphql book, snowtooth.herokuapp.com. This was simpler, so the curl request was simpler, and the information I pasted into jmeter was less, but I still got the error: GET query missing using Protocol: HTTP, server name: snowtooth.herokuapp.com, method: GET and Body Data: {"query":"query { allLifts { name}}"}, plus all the requisite headers in the Header Manager
Not sure what your proprietary website implementation is, however this http://snowtooth.herokuapp.com/ can be tested like:
HTTP GET request:
HTTP POST request:
Also be aware that since JMeter 5.1 it's possible to create a JMeter test plan from CURL command, this http://snowtooth.herokuapp.com/ gives me the following CURL command:
curl 'http://snowtooth.herokuapp.com/' -H 'Accept-Encoding: gzip, deflate, br' -H 'Content-Type: application/json' -H 'Accept: application/json' -H 'Connection: keep-alive' -H 'DNT: 1' -H 'Origin: http://snowtooth.herokuapp.com' --data-binary '{"query":"{allLifts{name}}"}' --compressed
And when I import it to JMeter I can execute the requests successfully:

Special characters in curl post

I am trying to use the following curl
curl -k 'https://myhost.com:9091/nifi-api/access/token' -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' --data "username=$USERNAME&password=$PASSWORD" --compressed —insecure
But get an error with a % in the password saying
URLDecoder: Incomplete trailing escape (%) pattern
I have seen suggestions online to use --data-urlencode but then I get the following error.
The username and password must be specified.
How can I resolve this issue?
--data-urlencode is the way to go adding it multiple times, one per parameter
userh='vf&re'
passwordh='asdaf%'
curl 'http://127.0.0.1:8080/' --data-urlencode "username=$userh" --data-urlencode "password=$passwordh"
Let's start a netcat listener to check what was sent
netcat -l 8080
Received data:
POST / HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: curl/7.60.0
Accept: */*
Content-Length: 34
Content-Type: application/x-www-form-urlencoded
username=vf%26re&password=asdaf%25
Sending all parameters in one option will not work since password parameter gets lost triggering the server error "The username and password must be specified."
curl 'http://127.0.0.1:8080/' --data-urlencode "username=$userh&password=$passwordh"
Response:
POST / HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: curl/7.60.0
Accept: */*
Content-Length: 38
Content-Type: application/x-www-form-urlencoded
username=vf%26re%26password%3Dasdaf%25
First command from OP with --data will not work either as it sends the % sign as is triggering a server error that "sees" and incomplete percent encoded request.
POST / HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: curl/7.60.0
Accept: */*
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Length: 33
username=asdasdas&password=asdaf%
Based on this answer.

Ruby cURL POST Request not going through

I am using Paw, an application to test REST requests. I have the follow request working using the application but need to change it to use cURL to use in my ruby on rails application.
POST /rest/api/latest/result/TRUNKDEVQAUNIT-TESTANDRGITBUILDDEV-12/comment HTTP/1.1
Content-type: application/json
Accept: application/json
Authorization: Basic dWkud29ya2JvdDpFVmgzUFQ0dEch
Cookie: JSESSIONID=C851F60AFB4A83F12753B9CCBC745093
Host: bamboo10.com
Connection: close
User-Agent: Paw/2.2.5 (Macintosh; OS X/10.10.5) GCDHTTPRequest
Content-Length: 32
{"content":"here is a comment, for testing purposes“}
I think it should look something like this but it is not working. I did not add the real username and password (or host) in for security reasons. Any help would be much appreciated. Thank you!
`curl -X POST -u username:password --data {"body": "This is a comment, for testing purposes"} -H "Accept: application/json" -H "Content-type: application/json" https://bamboo.com/rest/api/latest/result/TRUNKDEVQAUNIT-TESTANDRGITBUILDDEV-12/comment`
After a little time, I found the correct way to do it. It appears I was missing a ' before and after the data, as well as changing the json element to be content and not body
curl -H "Accept: application/json" -H "Content-type: application/json" -X POST -u username:password -d '{"content": "This is a comment, for testing purposes"}' https://bamboo10.com/rest/api/latest/result/TRUNKDEVQAUNIT-TESTANDRGITBUILDDEV-12/comment

Cannot accept post in Sinatra using Curl

Just been tinkering with Sinatra and trying to get a bit of a restful web service going.
The error I'm getting at the moment is very specific though.
Take this example post method
post '/postMan/:someParam' do
#Edited here. This code can be anything. 411 is still the response
puts params[:someParam]
end
Seems simple enough. Take a param, make an object out of it, then go store it in whatever way the objects save method defines.
Heres what I use to post the data using Curl
$curl -I -X POST http://127.0.0.1/postman/123456
The only problem is, I'm getting 411 back and have no idea why.
To the best of my knowledge, 411 is length required. Here is the trace
HTTP/1.1 411 Length Required
Content-Type: text/html; charset=ISO-8859-1
Server: WEBrick/1.3.1 (Ruby/1.9.2/2011-07-09)
Date: Fri, 02 Mar 2012 22:27:09 GMT
Content-Length: 303
Connection: close
I 'Cannot' change the curl message in any way. So might anyone have a way to set the content length to be ignored in sinatra? Or some fix which doesn't involve changing the curl request?
For the record, it doesn't matter whether I use the parameters in the Post method or not. I could have some crazy code inside it, it will still throw the same error
As others said above, WEBrick wrongly requires POST requests to have a Content-Length header. I just pass an empty body, because it's less typing than passing in the header:
curl -X POST -d '' http://webrickwhyyounotakeemptyposts.com/
Are you sure you're on port 80 for your app?
When I run:
ruby -r sinatra -e "post('/postMan/:someParam'){puts params[:someParam]}"
and curl it:
curl -I -X POST http://127.0.0.1:4567/postMan/123456
HTTP/1.1 200 OK
X-Frame-Options: sameorigin
X-XSS-Protection: 1; mode=block
Content-Type: text/html;charset=utf-8
Content-Length: 0
Connection: keep-alive
Server: thin 1.3.1 codename Triple Espresso
it's ok. Had to change the URL to postManthough, your example threw a 404because you had postman.
The output was also as expected:
== Sinatra/1.3.2 has taken the stage on 4567 for development with backup from Thin
>> Thin web server (v1.3.1 codename Triple Espresso)
>> Maximum connections set to 1024
>> Listening on 0.0.0.0:4567, CTRL+C to stop
123456
Ah. Try it without -I. It's probably sending a HEAD request and as such, not sending what you expect. Use -v if you want to show the headers.
curl -v -X POST http://127.0.0.1/postman/123456
curl -v -X POST -d "key=val" http://127.0.0.1/postman/123456
WEBrick erroneously requires POST requests to include the Content-Length header.
curl -H 'Content-Length: 0' -X POST http://example.com
Standardly, however, POST requests don't require a body and therefore don't require the Content-Length header.

Resources