mozvat / WSPAPIPrototype

Web Services 2.0 prototype work.
1 stars 2 forks source link

How far do you normalize the functionality into the URL verses a enum in the json paylod #24

Open mozvat opened 11 years ago

mozvat commented 11 years ago

For example.

http://mercuryrestapi.azurewebsites.net/api/transaction/credit/sale

or do you do

http://mercuryrestapi.azurewebsites.net/api/transaction/

public class PostTransaction
{
    public string TranType { get; set; }  //Credit/Gift/Loyalty/Debit/FSA/ACH/Paypal
    public string TranCode { get; set; }  //Sale/Void/Return/Add/Subtract/Redeem/Issue

.. }

esear commented 11 years ago

I would personally lean towards moving things to the URL. I think it makes the services simpler to describe, document and test. For example, when describing to a developer in the documentation how to process a return. (I might be over-simplifying this, but bear with me for the sake of an example)

OPTION 1: generic resource (transaction) with details in the body of the POST

  1. submit to this URL POST /payments/transaction/
  2. change the JSON object you submit to match a loosely typed format of [insert return object here]
  3. now the documentation has to describe all of the different variations of objects that can be submitted and which ones have required vs optional fields

OPTION 2

  1. Submit to this URL POST /payments/transaction/credit/return/[merchantID] body of the PUT { "account": "########", "amount": "13.54", "currency": "usd" }

The fields are all required, and the URL self-describes. This makes it very easy for the developer to know how to use it. reference: http://looselyconnected.wordpress.com/2011/02/01/a-proposal-for-rest-and-verbs/

dmurphy7299 commented 11 years ago

That looks very slick from a REST only perspective but I have reservations. (disclaimer, I've got little rest/json experience). My thoughts are "if I have to pass in a JSON body anyway, why not just put the MerchantID there? Why make me manipulate the URL for every call I make to the endpoint? I'd prefer a simple URL. I am also thinking that the more we manipulate the URL, and the less we put in the payload, the less similar it becomes with the SOAP/XML integration we provide.

esear commented 11 years ago

Excellent, thanks Dan. I think it is especially valid to debate whether or not the MerchantID is present in the URL. It probably does make more sense to include that in the BODY (or a HEADER field).

But I think the essence of Matt's question is whether we take the approach of A) generic 'transaction' and the details for a particular transaction (sale, return, void, preAuth, etc) are specified within the body, or B) explicit services (/payments/sale, /payments/return, /payments/void, etc) where the content of the BODY might be specific to that particular call.

I believe the later is easier to describe, document and integrate, and is the standard approach for REST. By following standard REST (and not an RPC-style implementation), we can take advantage of tools and documentation built to support REST. For example Swagger - simple self-documentation of REST APIs (https://developers.helloreverb.com/swagger/) Postman - a simple REST client (Chrome browswer plugin, https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm)

We need to agree upon this approach before we get too far down the implementation of a test instance. I believe this decision is core to our new Web Services, and if it wasn't obvious I feel strongly about the decision. :) I think this involves both product and architecture, because it is how our Developers will integrate and is under the umbrella of Developer experience.

If you want to get some background on REST, I put a couple O'Reilly e-books on the shared drive here: T:\Departments\Product\Shared\Mercury Web Services RESTful Web Services REST API Design Rulebook

dmurphy7299 commented 11 years ago

Yeah I was stewing on that debate in my head over the weekend.

More thoughts…

Option A. This will work but agree it is very dependent on very good documentation because the method signature is not as easily discoverable. The developer, once integrated to the endpoint, only has to deal with formatting the proper JSON or XML for the TranType/Code. No worrying about details of REST URLs, method names/signatures. But again, must be clearly documented.

Option B. B looks great to me but would keep key/ID fields out of the URL like CouponID, ProgramID, MErchnatID, etc. Aside from simplicity, there might even be security concerns with passing around key IDs like MerchantIDs in the URL. With option B, I feel it dovetails more with our SOAP implementation. That way you can have similar method names on the SOAP end points as well so that our REST and SOAP implementations are somewhat consistent even though different technologies. I’m hoping with our focus on REST, we aren’t forgetting our SOAP implementations. A Visual Studio c# web reference to a soap end point using intellisense is so damn easy to program against. Being a Microsoft guy, I would choose that over REST.

REST /payments/Sale {MerchantID:1234; PurchaseAmount:10.50}

SOAP soap:Body

Whichever path we go down, I believe it’s the integration guide, documentation, and sample code that is the key to making this easy. Having said all of that, from a programmers standpoint, I’d rather have option B. I feel it makes for easier maintenenace of code. dm From: erik sear [mailto:notifications@github.com] Sent: Monday, March 18, 2013 10:54 AM To: mozvat/WSPAPIPrototype Cc: Dan Murphy Subject: Re: [WSPAPIPrototype] How far do you normalize the functionality into the URL verses a enum in the json paylod (#24) Excellent, thanks Dan. I think it is especially valid to debate whether or not the MerchantID is present in the URL. It probably does make more sense to include that in the BODY (or a HEADER field). But I think the essence of Matt's question is whether we take the approach of A) generic 'transaction' and the details for a particular transaction (sale, return, void, preAuth, etc) are specified within the body, or B) explicit services (/payments/sale, /payments/return, /payments/void, etc) where the content of the BODY might be specific to that particular call. I believe the later is easier to describe, document and integrate, and is the standard approach for REST. By following standard REST (and not an RPC-style implementation), we can take advantage of tools and documentation built to support REST. For example Swagger - simple self-documentation of REST APIs (https://developers.helloreverb.com/swagger/) Postman - a simple REST client (Chrome browswer plugin, https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm) We need to agree upon this approach before we get too far down the implementation of a test instance. I believe this decision is core to our new Web Services, and if it wasn't obvious I feel strongly about the decision. :) I think this involves both product and architecture, because it is how our Developers will integrate and is under the umbrella of Developer experience. If you want to get some background on REST, I put a couple O'Reilly e-books on the shared drive here: T:\Departments\Product\Shared\Mercury Web Services RESTful Web Services REST API Design Rulebook — Reply to this email directly or view it on GitHubhttps://github.com/mozvat/WSPAPIPrototype/issues/24#issuecomment-15066589. CONFIDENTIALITY NOTICE: This email message is for the sole use of the named recipient(s) and may contain proprietary, confidential and privileged information. Any unauthorized review, use, disclosure, or distribution of this message or any attachments is expressly prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message. DISCLAIMER OF ELECTRONIC TRANSACTION: Unless expressly stated otherwise in a written communication in other than electronic form, or unless the author expressly designates a written portion of this electronic communication to be an "electronic signature" and clearly and unequivocally specifies the writing to which that electronic signature applies, nothing contained herein or in any communication in connection herewith shall satisfy the requirements for a writing, nor constitute a contract, agreement, or electronic signature, as those terms are defined in or contemplated by the Electronic Signatures In Global and National Commerce Act, 15 U.S.C. Section 7001 et seq, or the Uniform Electronic Transaction Act as adopted by any state or any other statute governing electronic transactions.
esear commented 11 years ago

One benefit I've read to putting the IDs in the URL is that it helps with load balancing. The device handling load balancing knows to send a particular request to the app server containing that particular ID. Also, it is consistent REST pattern. (for example, see here: http://developer.netflix.com/docs/REST_API_Conventions) Regarding security we would use HTTPS for all requests, so the IDs should never be visible.

From the REST API Design Rulebook, page 18 (we don't need to be purests, just providing as part of the conversation) Rule: Variable path segments may be substituted with identity-based values Some URI path segments are static; meaning they have fixed names that may be chosen by the REST API’s designer. Other URI path segments are variable, which means that they are automatically filled in with some identifier that may help provide the URI with its uniqueness. The URI Template syntax‡ allows designers to clearly name both the static and variable segments. A URI template includes variables that must be substituted before resolution. The URI template example below has three variables (leagueId, teamId, and playerId): http://api.soccer.restapi.org/leagues/{leagueId}/teams/{teamId}/players/{playerId} The substitution of a URI template’s variables may be done by a REST API or its clients.

sempf commented 11 years ago

Awesome discussion. It is largely a religious debate because there are benefits to both sides. I'll reread everyone's thoughts here in a bit and weigh in.