How to parse data from POST request - crystal-lang

I have a getter context : HTTP::Server::Context and a login form.
Now I want to parse data from context.request.body to get username and password which user input.
The response's content type: application/x-www-form-urlencoded

HTTP::Params.parse is what you're looking for:
# Based on the sample code in https://crystal-lang.org/ home
require "http/server"
server = HTTP::Server.new(8080) do |context|
context.response.content_type = "text/plain"
if body = context.request.body
params = HTTP::Params.parse(body)
context.response.print "Hello #{params["user"]? || "Anonymous"}!"
else
context.response.print "You didn't POST any data :("
end
end
puts "Listening on http://127.0.0.1:8080"
server.listen

Related

Does anyone know how to send API calls to an application using a __RequestVerificationToken? (Error: The cookie and the form field were swapped)

I'm trying to test out Anti Forgery tokens with API calls using VS2019 (C#) and RestSharp. What i'm doing is doing a GET to our login page to get 4 tokens/ cookies, then attaching these to a POST, with the Username and password, to try to log on. The first call succeeds and gives me a HTTP 200 and 4 cookies/ tokens back (ASP.NET_SessionId, XSRF-TOKEN, XSRF-COOKIE and a __RequestVerificationToken - all get attached as cookies (in the cookiecontainer) to the POST API call), the 2nd call however, fails with an HTTP 500 with this message: "Validation of the provided anti-forgery token failed. The cookie "__RequestVerificationToken" and the form field "__RequestVerificationToken" were swapped.". I'm including this token twice in my POST call - once as a cookie and once as part of the request body. Here is my code - can anyone shed any light on how to fix this error?
Thanks,
Jamie.
public void LogIn(string userName, string password)
{
// 1st call to get the cookies and tokens.
CommonProperties.Client = new RestClient { CookieContainer = new CookieContainer() };
CommonProperties.Client.BaseUrl = new Uri($"https://localhost:50000/Account/Login");
var request = new RestRequest(Method.GET);
request.AddParameter("ReturnUrl", "%2F", ParameterType.QueryString);
CommonProperties.Response = CommonProperties.Client.Execute(request);
CommonProperties.Client.BaseUrl = new Uri($"https://localhost:50000/Account/Login");
var requestToken = CommonProperties.Response.Cookies.Single(c => c.Name ==
"__RequestVerificationToken");
// 2nd call to log in.
request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddHeader("Accept-Encoding", "gzip, deflate, br");
request.AddHeader("Accept", "*/*");
request.AddHeader("Referer", $"https://localhost:50000/Account/Login");
request.AddParameter("undefined", $"__RequestVerificationToken=
{requestToken.Value}&UserName=userName&Password=password_321", ParameterType.RequestBody);
CommonProperties.Response = CommonProperties.Client.Execute(request);
}
I just solved this issue myself, so hopefully this answer helps anyone else who comes looking.
When you originally load the page with the GET it will return the cookie with the name of __RequestVerificationToken PLUS a form field with the same name. That form field will have a different value to the cookie's value, and in your POST you must set the body field for __RequestVerificationToken to have that form field's value, and the value of the cookie with the same name must match the cookie from the GET response.
If you have the same value for both the form field and the cookie, you get that rather misleading error that suggests the values are "swapped". They are not actually swapped, they're just matching, which is incorrect.

Flutter HTTP request using Basic Auth + passing user and password to receive user data back

I am a newcomer, not a professional coder (so be gentle), trying to build a Flutter app that must connect to a web/server API in HTTP.
According to the doc, to make a connection a header must be used, this header uses the Basic Ath method, with login and password + a content type.
Till that point I think I have found how to do (see code snippet hereunder) but I have to send a user id and a user password to the API in order to receive back user data. And I must humbly confess that I am stuck there...
I thank you in advance for your help!
Bernard
My code (after importing dart:convert et package:http/http.dart + installed the required dependencies) :
void brol() async {
String username = 'user';
String password = 'pass';
String userpass = '$username:$password';
String basicAuth =
'Basic ' + userpass;
print(basicAuth);
Response r = await get('https://www.adresse/login.php',
headers: {'authorization': basicAuth});
}
Many Thanks in advance for your answer,
Bernard
Your credentials should be in base64. You can visit the SO post in the comment.
Your code should be look like this:
main() async {
String username = 'user';
String password = 'pass';
String basicAuth =
'Basic ' + base64Encode(utf8.encode('$username:$password'));
print(basicAuth);
Response r = await get('https://www.adresse/login.php',
headers: <String, String>{'authorization': basicAuth});
print(r.statusCode);
print(r.body);
}
See also this blog post.

Moodle rest post returning error with feature core_user_get_users_by_field

Hi I'm new with moodle and I'm getting an error when calling the webservice.
Currently I'm trying to retrieve a user from moodle with the following function core_user_get_users_by_field and I'm using rest service to do so. I already managed to create a user thus I am authenticated to use the service.
the error that I'm receiving is
Missing required key in single structure: field
The bellow is the code was used to create a User. the issue that I got from the error is that the parameter that I need to send for the post is not formatted well. Does anyone know how to search correctly with this method or any other method.
String token = "token";
String postData = "username=username";
string createRequest = string.Format("http://domain/webservice/rest/server.php?wstoken={0}&wsfunction={1}&moodlewsrestformat=json", token, "core_user_get_users_by_field");
// Call Moodle REST Service
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(createRequest);
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
// Encode the parameters as form data:
byte[] formData =
UTF8Encoding.UTF8.GetBytes(postData);
req.ContentLength = formData.Length;
// Write out the form Data to the request:
using (Stream post = req.GetRequestStream())
{
post.Write(formData, 0, formData.Length);
}
// Get the Response
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
Stream resStream = resp.GetResponseStream();
StreamReader reader = new StreamReader(resStream);
string contents = reader.ReadToEnd();
// Deserialize
JavaScriptSerializer serializer = new JavaScriptSerializer();
if (contents.Contains("exception"))
{
// Error
MoodleException moodleError = serializer.Deserialize<MoodleException>(contents);
}
else
{
// Good
}
The webservice core_user_get_users_by_field needs an associative array given as parameter with the following key:values
'field': 'id'
'values': array of integers (must be an array, possibly with just one value)
In PHP it would be, for example:
$parameters = array('field' => 'id', 'values' => array(13));
It means: the user whose 'id' has the value of 13. Of course, you can use other parameters as well: ('field'=>'lastname', 'values'=> array('Smith'))
The parameters you can choose are the fields of the Moodle 'user' table.
Try to build these parameters in your postData variable.
Here's URL that work with my put this url in postman and set http method to post method
hostname/webservice/rest/server.php?wstoken=any_token&wsfunction=core_user_get_users_by_field&field=email&values[0]=h#fci.com
&moodlewsrestformat=json

Sending html content in mails using MailGun

How can we set html tags inside the mail content while sending mail using mailgun api? When I send it, the tags are displaying as it is.
But in smtp, we can set it as , isBodyHtml=true
Here is the quick code example that can help you to send email in HTML format.
RestClient client = new RestClient();
client.BaseUrl = new Uri("https://api.mailgun.net/v3");
RestRequest request = new RestRequest();
client.Authenticator = new HttpBasicAuthenticator("api", "key-XXX");
request.AddParameter("domain","yourdomain.com", ParameterType.UrlSegment);
request.Resource = "{domain}/messages";
//request.AddParameter("from", "Mailgun Sandbox <postmaster#sandboxc.mailgun.org>");
request.AddParameter("from", "from#mail.com");
request.AddParameter("to", to);
request.AddParameter("subject", subject);
request.AddParameter("text", "Text view of this email is not supported. Please view this email in HTML format. Thank you.");
//This will help you to send email in HTML format
request.AddParameter("html", body);
request.Method = Method.POST;
RestResponse stat = client.Execute(request) as RestResponse;
Hope this helps.
You can put your html content (with the tags) in the 'html' parameter when calling the Mailgun API.
Taken from Mailgun homepage (the last line is what you are asking for):
POST /messages
from = 'App <me#myapp.io>'
to = 'bob#gmail.com'
subject = 'Hello'
text = 'Welcome to our amazing app!'
html = '<p>Welcome to our amazing app!</p>'
Hope this helps

POST SOAP request in python getting error Response: 403 Forbidden

Please can anyone help out? i am trying to POST a SOAP request in python but i am getting the error Response 403: Forbidden. my code looks like below:
i am using the python imports:
import httplib
import base64
import string
#the message
message = """<soap:Envelope ...rest message </soap:Envelope>"""
host = "host.test.com"
url = 'https://server.etc.com' #End point url
i need to use the Basic Authentication too so i need the username and password in the http header
username = 'username'
password = 'password'
webSoapAction = 'urn:etc-com:document...'
#the Authentication in base64 encoding form for Basic Authentication
auth = 'Basic' + string.strip(base64.encodestring(username +'.'+ password))
webservice = httplib.HTTP(host) #connect to the server(host)
here i try to build the header:
webservice.putrequest("POST", url)
webservice.putheader("Host", host)
webservice.putheader("User-Agent", "Python http auth")
webservice.putheader("Content-Type:", "text/xml; charset=\"UTF-8\"")
webservice.putheader("Content-length", "%d" % len(message))
webservice.putheader("SOAPAction",webSoapAction)
webservice.putheader('Authorization', auth)
webservice.endheaders()
webservice.send(message)
i should get the response here
#get the response
statuscode, statusmessage, header = webservice.getreply()
print "Response: ", statuscode, statusmessage
print "Headers: ",header
res = webservice.getfile().read()
print 'Content: ', res
Two things regard to your basic auth header construction:
Put a single space between "Basic" and your secret
Use ':' instead of '.' in between username and password
So it should looks like:
#the Authentication in base64 encoding form for Basic Authentication
auth = 'Basic ' + string.strip(base64.encodestring(username +':'+ password))