Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free.

I am implementing a REST-like API and have just faced an interesting problem. There is a need to provide a resource with an open list of query parameters to filter the results. For example:

GET /api/items?field1=value1&field2=value2

Field names are configurable, so I don't have the complete list of possible names.

There are also parameters with special meaning, e.g. orderBy=field5

The problem is when there is a field with the same name as one of the pre-defined parameters. The API has to somehow distinguish between them.

Many command-line programs use two hyphens ("--") to mark the end of options and start of arguments. I think of something analogous in URLs.

Is there any good practice in this subject?

share|improve this question
2  
I use a ?filters=field:value approach. This way, I have a fixed set of Parameters and the 'configurable' stuff is hidden from the API –  Pinoniq Feb 13 at 9:48
    
@Pinoniq: I thought about an URL-encoded subquery, ie. ?filters=field1%3Dvalue1, but using another delimiter like ":" looks better. –  pkalinow Feb 13 at 12:12
    
Y, it makes for human&machine-readable format. field:value;otherfield:value just tells a nice story :) –  Pinoniq Feb 13 at 12:15

2 Answers 2

An easy solution is to add a prefix to all the query fields (or at least the customized). In my case the fields can be in different classes, e.g. "core" or "custom" so it is convenient to use prefixes to differentiate them. For example, "core.field1", "custom.field10". As a side effect, it will resolve the problem with conflicts. If someone adds a field called orderBy, it still will be able to be used for filtering without any conflict with the special parameter of the same name:

custom.orderBy=something&orderBy=field1
share|improve this answer

You can also mix the special fields with the field names. e.g.

/api/items?field1.orderByDesc=value1&field2=value2&field3.orderByAsc=value3

With this approach, you keep the field-specific filters close to the field without having to scan a separate parameter's value. Of course if you have some non-field related special params, such as pagination requests, then the "filters" special param is your best bet. You can make it less prone to conflicts by prefixing an improbable character sequence like

/api/items?field1.orderByDesc=value1&field2=value2&field3.orderByAsc=value3&z9x8y7rowStart=100&z9x8y7count=50

The z9x8y7 approach is similar to how PHP prefixes a $ before variable names.

On a different note, you may want to add a version number in the API itself, something like

/api/v1/items?........

This will allow you to keep multiple versions of your API alive, thus giving your consumers time to convert to a new version of your API when you release a new API. Some examples : http://www.lexicalscope.com/blog/2012/03/12/how-are-rest-apis-versioned/

share|improve this answer
    
I'm not sure if the url is the best place for the version number. A http header seems more RESTful. –  CodesInChaos Feb 18 at 7:48
    
Well, prefixing options with a strange value would make the queries less readable and hard to write manually... I would rather prefix the custom fields, making the name conflict impossible. –  pkalinow Feb 20 at 14:22

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.