Welcome to the SRP Forum! Please refer to the SRP Forum FAQ post if you have any questions regarding how the forum works.

Pass through services

Two pronged question this one.

Using the example url from the documentation

'www.myapplication.com/api/customers/5678/invoices/1234'

My understanding is that the endpoint is in this case '1234'.
What I don't understand is how the frameworks should end up there.
If either of the sample services routines for 'users' or 'contacts' were used to create a http_customers_services routine then it would return the customers record '5678'. The remaining component of the url is ignored.

Begin Case Case Len(Service) // This means the URL ends with /contacts/<id>. The client is requesting a specific user item. SelfURL = HTTP_Services('GetSelfURL') Begin Case Case HTTPMethod _EQC 'GET' ; GoSub GetItem Case HTTPMethod _EQC 'OPTIONS' ; GoSub OptionsItem Case HTTPMethod _EQC 'POST' ; GoSub PostItem Case HTTPMethod _EQC 'DELETE' ; GoSub DeleteItem Case Otherwise$ ; ValidMethod = False$ End Case Case HasGetString

I can follow how the http_entry_point_services is a pass through service in that it doesn't have the 'Len(Service)' condition and only checks firstly for service being null or specific services.
The other routines also check for service being null but that's the last condition which incidentally makes the 'Otherwise' condition superfluous as far as I can tell. (You've got a service in which case do this or you don't have a service so do this)

I guess in this example, the url could make sense if all customers had received invoice numbers unique to themselves but not necessarily unique across all customers but I don't understand how you would reach the endpoint when certain segments of the url are variable.

Comments

  • www.myapplication.com/api/invoices/1234?customer=5678
  • CustomerId= HTTP_Services('GetQueryField', 'customer')
  • Thanks Barry but I think you misunderstood the question.
    I'm working from the documentation and trying to understand what I'm reading.
    I'm getting there, slowly.

    I wasn't asking for a different url but rather how the frameworks were meant to work with the example given.
    'www.myapplication.com/api/customers/5678/invoices/1234'

    I've since noticed that the various next variables have values at the point of reading the customer record so I assume some intelligent application of those and another call to http_services('RunHTTPService', .....) would do the trick. I'll keep experimenting.
  • Mark,

    You've brought up a variety of issues and I'm worried that if I attempt to address them all at once it will make the answers muddied. All me to focus on the "pass through" question. If you want me to address other issues just respond to this thread or create a new one.

    The issue regarding "pass through" services is actually something I am improving right now with yet another release of the SRP HTTP Framework package. I might even suggest holding off on doing any more testing because the new version will make this so much easier and it will introduce some significant changes (translation: some re-writing of your existing HTTP service routines will be necessary). I'll leave that up to you to decide.

    From an API design perspective, my recommendation would be to make /invoices a top-level service. I know you are using my example, but I should change it to something else (yet another task). Nevertheless, there may very well be a need for a service to follow the URL pattern you've provided. So, let's explore this.

    Keep in mind that any of the pre-existing services provided are merely there to help you grasp the concept. There will be times when you need to modify the logic that is executed for a given URL and a given HTTP method. As you noted, your URL will ordinarily flow into the GetItem gosub. The Users and Contacts services assume you only need to collect the record corresponding to the URL segment containing the Key ID and return back to the client.

    No service will automatically flow into another service without your say so. That's the purpose of the RunHTTPService service. So, what you need to do is to call RunHTTPService in the GetItem gosub as you see fit. If you need to qualify the customer ID before retrieving the invoice number, then make sure you put conditional logic for that.

    The tricky part is making sure the RunHTTPService service knows that you want to call the /invoices service rather than the /5678 service. If you do nothing, then the framework will just assume the next segment (i.e., 5678) is the next service when, in fact, 5678 is a customer ID. So, you need to do a little manipulation of the variables before calling RunHTTPService. However you arrive there, here are the values that will need to be passed in:

    ServiceHandler = 'invoices'
    Service = 1234
    URL = ''
  • Thanks Don.

    You've addressed several questions there that I wasn't even sure I knew how to ask.
    The first few times I read through the documentation I couldn't understand why /invoices wasn't a top-level service but then I read a different example explaining REST today which followed a similar pattern and enabled me to understand yours better so I'm glad you explored it.

    I accept the pre-existing services are provided to help us newbies grasp the concept and they do help but this was one concept I wasn't grasping. When that happens, I'm hesitant to change too much logic in case I break the fundamentals. Your further explanation reassures me I was heading in the right direction so now I can continue to experiment.
  • This in the GetItem gosub looks like the simplest way to do the trick

    If Len(NextService) then * HTTP_Services('RunHTTPService', NextServiceHandler, NextService, NextURL) HTTP_Services('RunHTTPService', NextService, NextURL, "") end
  • Mark,

    Seems like a sensible way to handle this. FWIW, the next version will only have two arguments: HTTPService and RemainingURL. These are roughly the same as the NextServiceHandler and NextURL arguments.
  • I'll wait and see how that pans out
Sign In or Register to comment.