Iron Router: Escape a '?' in an incoming Twilio message - meteor

This is probably straightforward, but I couldn't find any direct answers:
I am writing a bot that answers questions asked through SMS. Twilio routes the questions to a webhook, and I extract the body of the message and the sender's phone number to prepare the reply. This works well when the SMS body doesn't include ? (as most questions do). When it does, the request is truncated after the ? and I can't read the number field.
Example:
Router.route('/twilio/', function() {
console.log('%j', this.params.query);
var number = this.params.query.From;
var body = this.params.query.Body;
var args = {
number: number,
message: body
}
this.response.end(Meteor.call('sendMessage', args));
}, {
where: 'server'
});
Here is the log when the question is asked with a ? (e.g. "How are you doing today?")
{"ToCountry":"US","ToState":"MI","SmsMessageSid":"SM7bb1aee8c38c567e916c715672b5a201","NumMedia":"0","ToCity":"OXFORD","FromZip":"07950","SmsSid":"SM7bb1aee8c38c567e916c715672b5a201","FromState":"NJ","SmsStatus":"received","FromCity":"CALDWELL","Body":"How are you doing today"}
Here is it without the ? (e.g. "How are you doing today")
{"ToCountry":"US","ToState":"MI","SmsMessageSid":"SM00d6a0c1bfec40c2372ed2cc255af918","NumMedia":"0","ToCity":"OXFORD","FromZip":"07950","SmsSid":"SM00d6a0c1bfec40c2372ed2cc255af918","FromState":"NJ","SmsStatus":"received","FromCity":"CALDWELL","Body":"How are you doing today","FromCountry":"US","To":"+1xxxxxxxxxx","ToZip":"48367","NumSegments":"1","MessageSid":"SM00d6a0c1bfec40c2372ed2cc255af918","AccountSid":"ACc8f77bee1430f42600b6f83d7174384c","From":"+1234567890","ApiVersion":"2010-04-01"}
I couldn't find any way to have Twilio encode the GET request. Barring that is there a way for Iron Router to escape special characters within the message body?
If not, is the only solution converting to POST request?
Thanks!

Related

Uri.https on Flutter is limiting the length of my url

I'm trying to make a get request to Firebase. In my url, I have to send the auth token which is very long (more than 900 characters). I create the url this way:
var url =
Uri.https('firebaseio.com', '/mydb.json?auth=$authToken&orderBy="userId"&equalTo="$userId');
But the url is not complete when I print it (the last characters are always lacking) and hence the request does not work. Anyone knows a solution for that?
Your URL isn't actually being cut. The print function can have a limit on its line length when being using in Flutter. Look elsewhere for your issue.
It likely has something to do with your misuse of quotes within your string. It's not normal to have quotes in your query parameters that are opened but not closed.
You can also improve this code by using the optional third queryParameters parameter of the Uri.https constructor to handle your query parameters:
var url = Uri.https(
'firebaseio.com',
'/mydb.json',
{
'auth': authToken,
'orderBy': '"userId"',
'equalTo': '"$userId"',
},
);

Send a File as well as parameters (through JSON) inside one HTTP request

I am creating a server using Go that allows the client to upload a file and then use a server function to parse the file. Currently, I am using two separate requests:
1) First request sends the file the user has uploaded
2) Second request sends the parameters to the server that the server needs to parse the file.
However, I have realised that due to the nature of the program, there can be concurrency problem if multiple users try to use the server at the same time. My solution to that was using mutex locks. However, I am receiving the file, sending a response, and then receiving the parameters and it seems that Go cannot send a response back when the mutex is locked. I am thinking about solving this problem by sending both the file and the parameters in one single HTTP request. Is there a way to do that? Thanks
Sample code (only relevant parts):
Code to send file from client:
handleUpload() {
const data = new FormData()
for(var x = 0; x < this.state.selectedFile.length; x++) {
data.append('myFile', this.state.selectedFile[x])
}
var self = this;
let url = *the appropriate url*
axios.post(url, data, {})
.then(res => {
//other logic
self.handleParser();
})
}
Code for handleParser():
handleNessusParser(){
let parserParameter = {
SourcePath : location,
ProjectName : this.state.projectName
}
// fetch the the response from the server
let self = this;
let url = *url*
fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(parserParameter),
}).then( (response) => {
if(response.status === 200) {
//success logic
}
}).catch (function (error) {
console.log("error: ", error);
});
}
The question is not really about Go or reactjs or any particular software library.
To solve your problem you'd first need to understand how HTTP POST works,
hence I invite you to first read this intro on MDN.
In short:
There are multiple ways to encode the data sent in a POST request.
The way the receiver should deal with this data depends on how it's encoded by the sender.
The sender has to communicate the encoding with its request — usually via the Content-Type header field.
I won't go into the details of possible encodings — the referenced introductory material covers them, and you should do your own research on them, but to maybe recap what's written there, here is some perspective.
Back in the 80s and 90s the web was "static" and the dreaded era of JavaScript-heavy "web apps" did not yet come. "Static" means you could not run any code in the client's browser, and had to encode any communication with the server in terms of plain HTML.
An HTML document could have two ways to make the client rendering it to send something back to the server: a) embed an URL which would include query parameters; this would make the client to perform a GET request with these parameters sent to the server; b) embed an HTML "form" which, when "submitted", would result in performing a rather more complex POST request with the data taken from the filled in form.
The latter approach was the way to leverage the browser's ability to perform reasonably complex data processing — such as slurpling a file selected by the user in a specific form's control, encoding it appropriately and sending it to the server along with the other form's data.
There were two ways to encode the form's data, and they are both covered by the linked article, please read about them.
The crucial thing to understand about this "static web with forms" approach is that it worked like this: the server sends an HTML document containing a web form, the browser renders the document, the user fills the form in and clicks the "submit" button rendered by the browser; the browser collects the data from the form's controls, for entries of type "file" it reads and encodes the contents of those files and finally performs an HTTP POST request with this stuff encoded to the URL specified by the form. The server would typically respond with another HTML document and so on.
OK, so here came "web 2.0", and an "XHR" (XMLHttpRequest) was invented. It has "XML" in its name because that was the time when XML was perceived by some as a holy grail which would solve any computing problem (which it, of course, failed to do). That thing was invended to be able to send almost arbitrary data payloads; XML and JSON encoding were supported at least.
The crucial thing to understand is that this way to communicate with the server is completely parallel to the original one, and the only thing they share is that they both use HTTP POST requests.
By now you should possibly see the whole picture: contemporary JS libs allow you to contruct and perform any sort of request: they allow you to create a "web form"-style request or to create a JS object, and serialise it to JSON, and send the result in an HTTP POST request.
As you can see, any approach allows you to pass structured data containing multiple distinct pieces of data to the server, and the way to handle this all is a matter of agreement between the server and the client, that is, the API convention, if you want.
The difference between various approaches is that the web-form-style approach would take care of encoding the contents of the file for you, while if you opt to send your file in a JSON object, you'll need to encode it yourself — say, using base64 encoding.
Combined approaches are possible, too.
For instance, you can directly send binary data of a file as a POST request's body, and submit a set of parameters along with the request by encoding them as query-parameters of the URL. Again, it's up to the agreement between the client and the server about how the latter encodes the data to be sent and the former decodes them.
All-in-all, I'd recommend to take a pause and educate yourself on the stuff I have outlined above, and then have another stab at solving the problem, but this time — with reasonably complete understanding about how the stuff works under the hood, and how you intend to wield it.

Is there such a thing as an ordered pair in request parameters / query string? in GET request

I'm writing an endpoint where it logically makes sense to think of request parameters as coupled ordered pairs
(eg breed=labrador&name=fido, breed=dalmnation&name=mike etc)
Is there anything I can do to enforce this pairing from the request
(eg having a dog object such that dog1{breed=labrador&name=fido}&dog2{breed=dalmnation&name=mike} or am I to just read the parameters in order and know that given a query know that the order matters and I must trust the ordering of the parameters would follow breed,name breed,name etc?
For context my endpoint would accept [1,15] dogs in a GET request and am using Django if that makes a difference.
I'm sorry if this has been asked before or is covered elsewhere, I'm struggling to find the right words to use to find a solution on Google.
If you are using a GET request you could possibly put a json string inside one of the of the url encoded variables. Like this example with python request library:
import requests,json
dogs = [
{ "breed": "labrador", "name": "fido"},
{ "breed": "dalmnation", "name": "mike"}
]
payload = { "json": json.dumps(dogs) }
requests.get("http://endpoint", params = payload);
Then on the receiving end:
def my(request):
myDogs = json.loads(request.GET.get('json'))

Add Multiple WWW-Authenticate headers with OWIN

I want our service to advertise more than one authentication scheme: for example both Bearer and some custom scheme, say X-Custom. (I have an OWIN middleware component for each scheme). I take if from RFC 2616, sec 14.47 there is more than one way to do it:
Option a) multiple headers
WWW-Authenticate: Bearer
WWW-Authenticate: X-Custom
Option b) comma-separated list
WWW-Authenticate: Bearer, X-Custom
My preference would be option a) so a client only has to do something like Response.Headers.Exists("WWW-Authenticate", preferredScheme) instead of comma parsing the header (which the RFC says they should, but...)
However, Katana uses a dictionary for headers. Trying to add the second header throws an exception with "The key 'WWW-Authenticate' is already present in the dictionary."
Is there a way for a middleware component to inject more than one WWW-Authenticate header?
It is IDictionary<string, string[]>. Key is a string but value is an array of string. So, you just need to set the header like this.
app.Run(async (IOwinContext context) =>
{
context.Response.Headers.Add("WWW-Authenticate",
new[] { "Bearer", "X-Custom" });
// Some other code
});
UPDATE
I believe you are very kind to accept my answer as answer :). Thanks but not sure it answered your question and hence the edit. First of all, I did not get the point you tried to make, which is to add the different headers from different middleware and yet wanting to see them in different lines in the response. I do not think there is anyway to do this for standard HTTP headers like WWW-Authenticate. In fact, before I answered your question, I quickly wrote a small program to verify but the mistake I made was to misspell this header.
Because of that, I was actually getting the header values like this.
WWW-Authentciate: X-Custom
WWW-Authentciate: Bearer
Anyways, the following works in getting the header values in two lines.
app.Use(async (IOwinContext context, Func<Task> next) =>
{
context.Response.Headers.Set("WWW-Authenticate", "Bearer");
await next.Invoke();
});
app.Run(async (IOwinContext context) =>
{
var x = context.Response.Headers.Get("WWW-Authenticate");
context.Response.Headers.Remove("WWW-Authenticate");
context.Response.Headers.Add("WWW-Authenticate", new[] { "X-Custom", x });
});
However, this does not work for standard headers. Nonetheless, this is an interesting exercise but at the end of the day, there is no accepted standard in terms of the API here (as far as I know). Even if you somehow get this working the way you want, the moment you change an underlying OWIN component, say the server or host, you could get different behavior. After all, option a and option b are exactly the same and you should not see any difference if you are working on top of some library to read the headers, unless you do some low-level stuff.

Internet e-mail validation expression validates everything

I'm validating input in a asp.net page but the problem is it validates e-mails like hasangürsoy#şşıı.com
My code is:
if (Regex.IsMatch(email, #"\w+([-+.']\w+)*#\w+([-.]\w+)*\.\w+([-.]\w+)*"))
{ valid }
else { invalid }
EDIT:
I've written a question before especially to validate e-mail addresses including Turkish characters but now I don't want users to be able to input mails with Turkish characters because users mostly type Turkish characters by mistake and I cannot send mails to these addresses.
Why don't you just use build-in System.Net.Mail.MailAddress class for email validation?
bool isValidEmail = false;
try
{
var email = new MailAddress("hasangürsoy#şşıı.com");
isValidEmail = true;
{
catch (FormatException x)
{
// gets "An invalid character was found in the mail header: '.'."
}
RFC3692 goes into great detail about how to properly validate e-mail addresses, which currently only correctly handle ASCII characters. However this is due to change, and hence your validation should be as relaxed as possible.
I would likely use an expression such as:
.+#.+
which would ensure you're not turning people away because your regular expression gives them no choice.
If the e-mail is important you should be following it up with verification usually done via sending an e-mail to the supplied address containing a link.
I recommend you reading this:
http://www.codeproject.com/KB/validation/Valid_Email_Addresses.aspx

Resources