Right way to accommodate an HTTP GET that could "skip" to a POST? - http

Let's say you have a HTTP GET request which could be skipped in some circumstances. For example, imagine you have:
GET /orders/new, which lets you pick what flavor of ice cream you want
POST /orders, which makes a new ice cream order
Normally, GET /orders/new shows you the list of flavors and a Submit button. But if there's only one flavor available today, you'd like to just POST the order to avoid having the user make a useless decision. (We'll imagine this is a universe in which everyone likes all flavors equally and so will always be happy with your dictatorial ice cream choice.)
It doesn't seem correct to do something like "redirect to POST" from a GET request, since that wouldn't be idempotent. So then what's the right way to do this:
if there's more than one flavor: let the user pick the flavor(s) they want for their order
if there's only one flavor: pick the only flavor for their order and immediately make the order
either way, wind up with a newly POSTed order

It's a GET, it should never result in a POST. Period. If you want to avoid the choice, avoid doing the GET entirely somewhere in the flow before the GET /orders/new. Maybe I only want to see the flavors, but not actually proceed with an order.

Related

Single term answer to Alexa Skill

Background
I'm writing an Alexa Skill and looking to get pieces of information from the user.
The following conversation for example:
Alexa: What month were you born at?
User: April
Alexa: Good. And what was your favorite movie?
User: April
The problem
Given the following utterances:
GetMonthIntent {month}
GetMovieIntent {movie}
Once a user answers April for the second time, the GetMonthIntent might be triggered.
What I have tried
Asking the user to specify which piece of information is giving by using the following utterances:
GetMonthIntent Month {month}
GetMovieIntent Movie {movie}
The question
What is the right way to make Alexa wait for a single term answer based on the current context?
In the same vein as the other answers here, you should take a look at the newest Node.JS library here, which handles state out of the box:
https://github.com/alexa/alexa-skills-kit-sdk-for-nodejs#making-skill-state-management-simpler
You could define:
State_Launch
State_Month
State_Movie
And then return the proper error response if anything other than the GetMovieIntent or GetMonthIntent (etc.) intents are called in the wrong state.
You would have to do data validation on the server side to make sure the "month" is a valid one, and movies are even harder to validate unless you have a list of expected values. That is, if you care to parse them for use beyond repeating back.
Unfortunately, there is no solution. There is no way to specify the 'context' in which a user reply should be interpreted, so you have to tell the user "what was your favorite movie? Please say 'my favorite movie is' and then the name of the movie".
Here are two ASK feature requests that I think would address your issue:
https://forums.developer.amazon.com/content/idea/41062/creating-something-to-help-with-more-structured-qu.html
https://forums.developer.amazon.com/content/idea/55525/allow-a-response-to-specify-a-set-of-expected-inte.html
Personally I think this is fairly important so I voted for those, but they are not near the top.
I ran into this same problem when I created the "Who's on First? Baseball Skit" skill. I handled this by:
Create a sequence number for each response given by Alexa
Write this number to the "session" in the response.
The session is then passed back to your skill by Alexa in the next request.
Read the sequence number from the request to know what the previous question was.
If a given intent could be the answer to multiple questions (eg. month and movie in your case) then use the sequence number to determine which it is.
This should give you ideas on how to deal with repeated answers. The session is quite easy to use. Other options include writing the userId and status to a database like DynamoDB, but I find that the session works in most cases.

SCORM to xAPI sessions and re-answering Activity + changing Score

I'm coming from a SCORM end and trying to figure out two related issues with how to do update and find the most recent data (ie, looking for best practices).
In SCORM I'd have a set of activities that would all store their answers and scores (easily understandable from the docs etc). The "how" I'm after is specifically related to resuming the set of activities multiple times, and hitting "reset" and submitting a different answer to a single activity after a statement has been sent in.
From what I read with xAPI it states that statements are immutable - so how would I go about this.
My first thought was that I'd make the statement id generated from the activity id and void the old answer when it changes - but that sounds wrong (not least because it reads like you can't re-use the id even with voiding).
So it looks like the Statement id needs to be unique, which would mean that multiple identical Objects would be found - so would I have to look through every attempt and check for the latest one?
I'm currently looking at using xAPIWrapper in the middle.
Moving from SCORM to xAPI requires a change of mindset. SCORM deals with statuses which get updated; xAPI logs events like a journal.
You can think of it like Facebook. You post a photo of your new cat; a month later you post a photo of your cat 1 month older. There's no need to go back and delete the old post. If you want the latest photo of your cat you just go and get the most recent photo tagged "Ryochet's cat". You can also look at older photos to see how your cat developed. xAPI is like that activity stream on Facebook.
So, if somebody scores 10 points on their first attempt, then 20 points on their second attempt, you'd simply send a second set of statements about the 2nd attempt. There's no need to get rid of the statements about the old attempt, that happened and is useful data to see how the learner developed.

Ocassionally-unreliable DATE field of http response

We're interested in the rough timezone of the user, give or take a few hours, and for reasons we don't trust the user's device clock.
One cheap and easy thing we tried is to post a GET (a HEAD would work too) to (eg) google.com, and look for the DATE field of the header. This is, by the http standard, always in GMT. This may fall foul of caching, so we added a ?rng=XXXXXX to the end.
However in some cases the date field seems to be way off. Like, days off. The previous and next request get the correct date. Now maybe I just need to add more digits to my cache-beating rng field, but could something else be going on? Are there any flaws or downsides in this plan, considering we don't care about second-accuracy?
We seem pretty sure that given our player install base, and the frequency of these checks, and the poorness of our random suffix, that google/someone in between was able to cache them successfully.
Seems like a good rule not to use http headers for authoritative time, unless you control the server and can send non-caching responses.

Advice needed on REST URL to be given to 3rd parties to access my site

Important: This question isn't actually really an ASP.NET question. Anyone who knows anything about URLS can answer it. I just happen to be using ASP.NET routing so included that detail.
In a nutshell my question is :
"What URL format should I design that i can give to external parties to get to a specific place on my site that will be future proof. [I'm new to creating these 'REST' URLs]."
I need an ASP.NET routing URL that will be given to a third party for tracking marketing campaigns. It is essentially a 'gateway' URL that redirects the user to a specific page on our site which may be the homepage, a special contest or a particular product.
In addition to trying to capture the referrer I will need to receive a partnerId, a campaign number and possibly other parameters. I want to provide a route to do this BUT I want to get it right first time because obviously I cant easily change it once its being used externally.
How does something like this look?
routes.MapRoute(
"3rd-party-campaign-route",
"campaign/{destination}/{partnerid}/{campaignid}/{custom}",
new
{
controller = "Campaign",
action = "Redirect",
custom = (string)null // optional so we need to set it null
}
);
campaign : possibly don't want the word 'campaign' in the actual link -- since users will see it in the URL bar. i might change this to just something cryptic like 'c'.
destination : dictates which page on our site the link will take the user to. For instance PR to direct the user to products page.
partnerid : the ID for the company that we've assigned - such as SO for Stack overflow.
campaignid : campaign id such as 123 - unique to each partner. I have realized that I think I'd prefer for the 3rd party company to be able to manage the campaign ids themselves rather than us providing a website to 'create a campaign'. I'm not
completely sure about this yet though.
custom : custom data (optional). i can add further custom data parameters without breaking existing URLS
Note: the reason i have 'destination' is because the campaign ID is decided upon by the client so they need to also tell us where the destination of that campaign is. Alternatively they could 'register' a campaign with us. This may be a better solution to avoid people putting in random campaign IDs but I'm not overly concerned about that and i think this system gives more flexibility.
In addition we want to know perhaps which image they used to link to us (so we can track which banner works the best). I THINK this is a candiate for a new campaignid as opposed to a custom data field but i'm not sure.
Currently I am using a very primitive URL such as http://example.com?cid=123. In this case the campaign ID needs to be issued to the third party and it just isn't a very flexible system. I want to move immediately to a new system for new clients.
Any thoughts on future proofing this system? What may I have missed? I know i can always add new formats but I want to use this format as much as possible if that is a good idea.
This URL:
"campaign/{destination}/{partnerid}/{campaignid}/{custom}",
...doesn't look like a resource to me, it looks like a remote method call. There is a lot of business logic here which is likely to change in the future. Also, it's complicated. My gut instinct when designing URLs is that simpler is generally better. This goes double when you are handing the URL to an external partner.
Uniform Resource Locators are supposed to specify, well, resources. The destination is certainly a resource (but more on this in a moment), and I think you could consider the campaign a resource. The partner is not a resource you serve. Custom is certainly not a resource, as it's entirely undefined.
I hear what you're saying about not wanting to have to tell the partners to "create a campaign," but consider that you're likely to eventually have to go down this road anyway. As soon as the campaign has any properties other than the partner identifier, you pretty much have to do this.
So my first to conclusions are that you should probably get rid of the partner ID, and derive it from the campaign. Get rid of custom, too, and use query string parameters instead, should it be necessary. It is appropriate to use query string parameters to specify how to return a resource (as opposed to the identity of the resource).
Removing those yields:
"campaign/{destination}/{campaignid}",
OK, that's simpler, but it still doesn't look right. What's destination doing in between campaign and campaign ID? One approach would be to rearrange things:
"campaign/{campaignid}/{destination}",
Another would be to use Astoria-style indexing:
"campaign({campaignid})/{destination}",
For some reason, this looks odd to a lot of people, but it's entirely legal. Feel free to use other legal characters to separate campaign from the ID; the point here is that a / is not the only choice, and may not be the appropriate choice.
However...
One question we haven't covered yet is what should happen if/when the user submits a valid destination, but an invalid campaign or partner ID. If the correct response is that the user should see an error, then all of the above is still valid. If, on the other hand, the correct response is that the user should be silently taken to the destination page anyway, then the campaign ID is really a query string parameter, not a part of the resource. Perhaps some partners wouldn't like being given a URL with a question mark in it, but from a purely REST point of view, I think that's the right approach, if the campaign ID's validity does not determine where the user ends up. In this case, the URL would be:
"campaign/{destination}",
...and you would add a query string parameter with the campaign ID.
I realize that I haven't given you a definite answer to your question. The trouble is that most of this rests on business considerations which you are probably aware of, but I'm certainly not. So I'm more trying to cover the philosophy of a REST-ful URL, rather than attempting to explain your business to you. :)
I think the URL rewriting is getting out of hand a little bit lately. Not everything belongs to the URL. After all, a URL is supposed to describe a resource that can be searched for, discovered or manipulated and it seems to me that at least the partner ID and the custom fields from above are not part of the resource.
Not to mention that that at some point you would like to actually keep the partner ID constant across multiple campaigns and that means that it is now orthogonal to the particular places they need to visit. If you keep these as parameters, you will allow your partners to access uniformly multiple resources on your website, while still reliably identifying themselves, so you can track their participation in any of your campaigns.
It looks like you've covered all of your bases. The only suggestion I have is to change
{custom}
to
{*custom}
That way, if you ever need to accept further parameters, you don't have to take the chance that old URLs will get a 404. For example:
If you have a URL that looks like:
campaign/PR/SO/123
and you decide in the future that you would like to accept a fourth and fifth parameter:
campaign/PR/SO/123/blah/foo
then the first URL will still be valid, because you're using a wildcard character in {*custom}. "blah/foo" would be passed as a string to your action. To get those extra two parameters, you would simply split the custom argument in your action by '/'. Add some friendly error handling if they don't exist and you've successfully changed the amount of information you can receive with a campaign URL without completely breaking URLs already in the wild.
Why not use URL encoded variables instead of routes? They're a lot more flexible - you can add any new features in the future while still maintaining 100% backwards compatibility. Admittedly, it's a little more trouble to type manually, but if there's all those parameters anyway, it's already no picnic.
http://mysite.com/page?campaign=1&dest=products&pid=15&cid=25
To me, this is much more indicative of what is really going on. Using paths implies a that a resource exists at that location. But really you're just providing a web service with various parameters, and this model captures that much more clearly. And in the future, you can add more parameters effortlessly. You can also default parameters if they are missing without messing anything up.
Not sure of the code in ASP, but it should be trivial to implement.
I think I'd look at doing it the way that SO does it's questions.
"campaign/{campaign-id}/friendly-name-of-campaign"
Create a mapping in your database when the campaign is created that associates all the data you need with an automatically generated id. The friendly name could be assigned basically the same way as a question is on SO -- by the user -- but you could also have an approval process that makes sure that it meets your requirements and is distinct from any existing campaign names. Your tracking company can track by the id and you can correlate that with your associated data with a simple look up.
What you have looks good for your needs. The other posts here have good points. But may not be suitable for you. One thing that you could consider with future proofing your links is to put a version number somewhere in there.
"campaign/{version}/{destination}/{partnerid}/{campaignid}/{custom}"
This way if you decide to completely change your format you can up the version to 2.0 (or whatever) and still keep track of the old links coming in.
I would do
/c/{destination}/{partnerid}/{campaignid}/?customvar=s
You should think about the hierarchy of the first parameters, you already got that managed quite well. Only if there's a hierarchy path segments should be used.
From your description, destination seems to be the broadest parameter, partnerid only works with destination, and campaingid is specific to a partner.
When you really need to add custom parameters I would go for query variables (they are not forbidden in REST), because these are not part of the hierarchy.
You also shouldn't try to be too RESTful here. After all, it's for a campaign and for redirecting to a final resource. So the URL you want to design here is not really a specific resource in the terms of REST.
Create an URL called http://mysite.com/gateway
Return an HTML form, tell your partners to fill in the form and POST it. Redirect based on the form values.
You could easily provide your partners with the javascript to do the GET and POST. Should be trivial.
The most important thing i have learned about REST URLĀ“s thats usually burried deep in some book or article:
The URL should point to a resource and the following ?querystring should have all the scoping information needed. DONT mix those two or you will have a design thats very hard to work with.
Other then that i fully agree with Craig Stuntz

Best Strategies for preventing addresses with PO Boxes?

I have a client which is shipping via UPS, and therefore cannot deliver to Post Office boxes. I would like to be able to validate customer address fields in order to prevent them from entering addresses which include a PO box. It would be best if this were implemented as a regex so that I could use a client-side regex validation control (ASP.NET).
I realize there's probably no way to get a 100% detection rate, I'm just looking for something that will work most of the time.
UPS also has tools that you can integrate to do this... that way you can verify an address exactly as to whether or not they will ship, what the cost would be, schedules, etc. I suggest visiting the UPS IT Solutions page for more information.
This should get you started. Test to see if the Address field matches this regex.
"^P\.?\s?O\.?\sB[Oo][Xx]."
Translation to English: That's a P at the beginning of the line, followed by an optional period and space, followed by an O, followed by an optional period, followed by a space, followed by "Box", followed by anything else.
You might be better off putting a disclaimer on the page warning that you can not ship to post office boxes, opposed to validating the input.
More than likely if you do create a regex that catches most of the P.O. Box scenarios, there's a good chance it'll also catch things you weren't intending (i.e. a customer with a street name containing the letters 'p' 'o' and 'box')
Unfortunately, UPS's online software allows P.O. Boxes to go through, but will choke on them once they're in the shipping channel.
In our case, our cart abandonment rate went up when we tried to gracefully prevent P.O. Boxes. We found it much more cost effective to leave it alone, accept the sale, bring it to the attention of customer service, and let them resolve it.
Of course, if you get a high incidence of P.O Boxes, this may not be the case for you.
I'd start with a regex ala Lizard (but use the "ignore case" flag :)), test on historical data, then iterate as you see what invalid inclusions and exclusions you see in testing.
Most shipping providers (for example FedEx) will validate the shipping address. For example, with FedEx web services, there is a call to validate a shipping address and get the estimated cost. This not only ensures that the address is not a PO Box, but also makes sure that the rest of the address is valid.
Regarding the OP's comment to Jason Coco's answer:
Since you're in a position to add regex validation to the shipping address, I assume that you have control of the application (i.e., you have the source and can modify it). If that's the case, then you should have the ability to, on reciept of the submitted data, check whether it is to be shipped via USPS, FedEx, or UPS and submit a request to the appropriate shipper-specific address validator, gaining all the benefits suggested in Jason's answer.
By making it shipper-specific, this would also allow you to avoid implementing one-size-fits-all rules, such as "no PO boxes because UPS doesn't deliver to them", even though the user can select non-UPS shippers who do deliver to PO boxes.
What if it doesn't start with "PO Box.." or "P.O. Box" ?
Example:
John Schmidt |
Silver Valley PO Box 3901 |
Whereswaldoville, SI. 78946
I used an onblur event for the address field to use a javascript function, indexOf, to recognize the input.toUpperCase "PO BOX" || "P.O" that is >= 0.
If either of these two searches are not found, the return is -1, otherwise, it will return the string's start position which will always be 0 or more.
This will ensure that lazy typing, 'po box,' 'p.o box,' and as well as 'p.o. box' will be recognized. I suppose you could add 'po. box' as well.
Anyway, the condition triggers an unobtrusive message to show that 'We can't ship to a PO Box address." It's a feature to not see it if it doesn't apply to you. Otherwise, for users who don't have js or css enabled, they'll just see the message. The only fail on this graceful degradation is if a user has css, but not js enabled (where they just won't see the message at all). I only came up with the solution today, but if I think of a better way, I'll come back to post it here.

Resources