Typesafe RPC shared between client/server but with REST methods - scala

I would like to know if there is a way to join RPC(so client know what he can call and server know what should he respond to) and HTTP Rest(so any other client, without shared codebase can make a call).
There is a lot of http libraries for scala(akka-http, http4s, etc.) and there is good RPC lib autowire. But I see no way to connect them. I know autowire is protocol agnostic, but it's a drawback here, because i would like to routing happened in http layer(e.g akka-http), not rpc(autowire).
I would like to know if it possible. If it is, is there any implementation ongoing?

endpoints is a work in progress in this direction (note: I am the author of this library). It provides means of defining an API made of HTTP endpoints (which verb, URL, etc. to use), and then it provides implementations that use such APIs as a client or as a server. It is compatible with Scala.js, so you can share your API definition between the client side and the server side of your application and benefit from statically type checked remote calls.
It is designed to give you full control over the usage of HTTP features (e.g. caching, headers, authentication, etc.).
Here is a basic API definition with two endpoints:
// POST /my-resources
val create: Endpoint[CreateMyResource, MyResource] =
endpoint(post(path / "my-resources", jsonRequest[CreateMyResource]), jsonResponse[MyResource])
// GET /my-resources/:id
val read: Endpoint[String, Option[MyResource]] =
endpoint(get(path / "my-resources" / segment[String]), option(jsonResponse[MyResource]))
You can then use it as follows from the client-side, to perform an actual call:
val eventuallyResource: Future[MyResource] =
create(CreateMyResource("foo", 42))
val eventuallyResource2: Future[Option[MyResource]] =
read("abc123")

Related

What is the difference between BasicHttpRequest and HttpGet, HttpPost, etc in Apache HTTP Client 4.3 ?

I am creating HTTP request using Apache HTTP Client version 4.3.4. I see there are some classes like HttpGet,... and there is also a class BasicHttpRequest. I am not sure which one to use.
Whats the difference and which one should be used in which condition ?
BasicHttpRequest is provided by the core library. As its name suggests it is pretty basic: it enforces no particular method name or type, nor does it attempt to validate the request URI. The URI parameter can be any arbitrary garbage. HttpClient will dutifully transmit it to server as is, if it is unable to parse it to a valid URI.
HttpUriRequest variety on the other hand will enforce specific method type and will require a valid URI. Another important feature is that HttpUriRequest can be aborted at any point of their execution.
You should always be using classes that implement HttpUriRequest per default.
I was just browsing the 4.3.6 javadoc attempting to locate your BasicHttpRequest and was unable to find it. Do you have a reference to the javadoc of this class?
I would be under the impression that BasicHttpRequest would be a base class providing operations and attributes common to more than one HttpRequest. It may be extremely generic for extension purposes.
To the first part of your question, use HttpGet, HttpPost etc for their specific operations. If you only need to HTTP/GET information then use HttpGet, if you need to post a form or document body, then use HttpPost. If you are attempting to use things like the Head, Put, Delete method, then use the correspoding HttpXXX class.

Two identical REST mappings with different HTTP request types

Let's assume we have two methods on the REST controller:
#ResponseStatus(HttpStatus.OK)
#RequestMapping(value = "/{userId}", method = RequestMethod.GET)
#ResponseBody
public UserDTO showUserDetails(#PathVariable("userId") Long userId) {
/* code here */
}
#ResponseStatus(HttpStatus.ACCEPTED)
#RequestMapping(value = "/{userId}", method = RequestMethod.POST)
#ResponseBody
public UserDTO editUser(#PathVariable("userId") Long userId, UserDTO userToEdit) {
/* code here */
}
So we have two identical URIs mappings, but supporting different HTTP requests. My question is: is this approach acceptable in terms of designing APIs? Or it is better to map second method to something like /{userId}/edit ?
Also, when using hateoas paradigm, the response will look somewhat strange:
"links":[{"rel":"self","href":"http://1localhost:8080/root/users/1"},{"rel":"edit","href":"http://localhost7:8080/root/users/1"}]
With 2 different URIs looking identical.
In terms of REST API design, you mapping is correct. For a given resource, you should interact with it via a single URI, In you example:
http://localhost:8080/root/users/1
And specify the operation via HTTP verbs.
Check the RESTful API HTTP methods in REST - Applied to web services, for an example.
I would definitely change the request mappings. For your editUser I'd add a /edit/ so your URL would look like http://localhost7:8080/root/users/edit/1
For the show you could add a /view/ to the URL, but that's not really necessary, but for the edit I'd personally prefer to have the URL be selfexplanatory
From a REST perspective what matters that you use the proper HTTP method and a single resource identifier (URL) is mapped only to a single resource. The URL structure does not matter. It matters only for you by routing the requests.
Your choice of method is bad. By edit you have to use PUT (full) or PATCH (partial) instead of POST. If you cannot use these methods because of some purposes (for example you use plain HTML forms to send requests), then you should use method override. For example send the real method in a _method param, in the body, in the query, or in a header. (It does not really matter which you choose because it is already an ugly workaround. Most ppl prefer the query.)
By choosing the URL most ppl prefer to use only nouns. This is because you don't map URLs to operations (like SOAP RPC), which are verbs (and probably nouns). For example POST /GetCurrentPrice. You map URLs to web resources, which are nouns for example GET /currentPrice.
REST is pretty simple. It uses existing standards to describe an uniform interface. Sadly most web developers do not know the HTTP standard. You should read at least the HTTP method definitions, the HTTP status code definitions and the URI RFC. These are the basics by REST.

Haskell as REST server

I would like to try Haskell on a smallish project which should be well suited to it.
I would like to use it as a backend to a small ajax application.
Haskell backend should be able to do authentication (basic, form, whatever, ...), keep track of user session (not much data there except for username) and to dispatch request to handlers based on uri and request type. It should also be able to serialize response to both xml and json format, depending on request parameter.
I suppose the handlers are ideally suited for Haskell, since the service is basically stateless, but I don't know where to start for the rest of the story.
Searching hackage didn't give me much hints.
Solution for pure haskell server would be prefered.
I've recently written a production quality web service for internal use. I used the following packages:
CGI & FastCGI — for basic web server interfacing
UrlDisp — for URL based dispatching
HDBC & HDBC-mysql — for database access
hexpat — for XML parsing (some requests/responses were XML based)
parsec — for configuration file parsing (on the server side)
binary &/or cereal — for binary data parsing (some requests/responses were binary based) (though I'd probably use attoparsec now)
Also, for a different project, I'm also using:
xhtml — XHTML combinator library
None of these are the highest level components available for Haskell, but they are all quite workable and fairly complete. I avoided the higher-level abstractions since I needed to fit this into an existing larger system, and these packages work just like similar components I've used in other web service projects.
I ran the service as a fastCGI based handler for Apache2 w/mod_fcgid. This appears to be a reliable and efficient set up. I suppose a Haskell based server, compiled together with the service might be faster, but this was pretty reasonable with very little work. I got > 1,400 requests per second on a quad-cpu, 2.6GHz, Linux server.
There are several Haskell pure servers. Most have their own APIs for your service code, though they are all pretty similar. Take a look at:
hack and hack-handler-simpleserver (which has an adapter to call code written to CGI/FastCGI directl: hack-handler-cgi, hack-handler-fastcgi)
Happstack
hyena (which uses the wai interface, and see wai-extra).
That's probably a lot to chew on. Let us know how it goes!
Meanwhile, if you want more information you can visit the HaskellWiki.
It's now May 2011, just an update on current trends.
I think most web development today is done with yesod or the snap frame work. both are very good and very nice developed (thanks to all the people who are involved!!). further there is also the wrap package.
My small REST example (or resful server). (ok maybe the example is not a real restful server, but it shows how you can handle GET/PUT requests, the rest is up to you..)
If you open http://localhost:8000/mytest in a browser, then "Get request" is displayed. If you make a PUT request with a rest-client (also to localhost:8000/mytest), the content of the request body is stored in "/tmp/restrq.txt".
This code is part of the Site.hs file of the Snap-Framework:
- | Constants
tempFilePath :: String
tempFilePath = "/tmp/restrq.txt"
-- | Helper Functions
-- Bytestring Conversion
strictToLazy :: B.ByteString -> BL.ByteString
strictToLazy x
| B.null x = BL.Empty
| otherwise = BL.Chunk x BL.Empty
lazyToStrict :: BL.ByteString -> B.ByteString
lazyToStrict = B.concat . BL.toChunks
getRequestString :: MonadSnap m => m B.ByteString
getRequestString = do message <- getRequestBody
return (lazyToStrict message)
-- | Action for PUT request
action :: Application ()
action = do message <- getRequestString
liftIO $ B.writeFile tempFilePath (B8.append (B8.pack "--- REST BODY ---\n") message)
-- | /mytest (GET and PUT requests possible)
mytest :: Application ()
mytest = method GET (writeBS "Get request") <|> method PUT action
-- | The main entry point handler.
site :: Application ()
site = route [ ("/", index)
, ("/mytest", mytest)
]
<|> serveDirectory "resources/static"
For a server that implements a JSON API I'm using scotty, which builds on WAI+Warp. It is incredibly easy to use, in particular if you've previously built applications with Sinatra.
I'm not sure how low-level you are trying to go. If you want to write your own server you could start from something like this:
http://lstephen.wordpress.com/2008/02/14/a-simple-haskell-web-server/
Alternately, if you are looking for a pre-built framework you could try HApps:
http://happs.org/
There is also a Ruby-On-Rails port. Turbinado or something.
Lastly, there are some getting started w/ CGI type tutorials. I've used this one:
http://www.haskell.org/haskellwiki/Practical_web_programming_in_Haskell (It was also suggested in #mdm's answer)
Good luck!
There are some useful links in
this question "What is the ecosystem for Haskell web development?"
I'm not sure about pure servers, but for small projects, which don't need a full-fledged web framework, I use the WAI library, which is also used by the Yesod framework.
Anyway, even if your application is simple, I would suggest a real framework, because Haskell web frameworks are usually not about being a large library of predefined stuff, but only about providing a clean concept for web applications, be them simple guestbooks or whole AJAX-enabled community applications.
Practical web programming in Haskell. There are a couple of modules you'll find useful, Text.XHtml and Network.CGI.

Restful and SOAP

How can I implement both restful and SOAP together?
You can't implement a single API which conforms to both REST and SOAP.
However, it is possible to create a system which exposes a RESTful API and a SOAP API with equivalent functionality.
In order to do so, the underlying implementation of the system should be independent of both APIs. If, for example, you were implementing your system with Java, the underlying implementation and each API should all be in independent packages. If Python, independent modules. Etc.
Ideally, if you had infinite time, each API would be fully designed to conform to the underlying paradigms of their architecture styles: the RESTful API would be properly oriented around resources and transfers of representations of their state, and the SOAP API would be properly oriented around procedures and their parameters and return values.
However, in order to save some time, it's possible to model a SOAP API after a REST API, by simply combining the resource names with the HTTP methods. The result is a kind of a REST-via-SOAP hybrid.
For example, if your REST API has a resource named Mailboxes, which supports GET, POST, PUT, and DELETE, and accepts and returns representations of type application/json, you could model the resource and its methods by creating the following SOAP methods:
get_mailboxes(url, options) returns jsonDoc
post_mailboxes(url, options, jsonDoc) returns jsonDoc
put_mailboxes(url, options, jsonDoc) returns jsonDoc
delete_mailboxes(url, options) returns nothing
I apologize if my notation is incorrect, I'm not all that familiar with SOAP.
You can expose the same service as SOAP based as well as RESTful. Axis2 with WSDL 2.0 has support for this.
Please see this article RESTful Web Services with Apache Axis2 - explains things in detail..
Thanks..
REST and SOAP are mutually exclusive concepts. You can't.
Given an arbitrary service there is nothing stopping you exposing both REST and SOAP interfaces to it. However, the nature of the service may lend itself to one method of access more than the other.
Make your Soap Service first with all your meta data annotations
Make sure you have a wsdlLocation inside of your #webserivce
Then you can add all your rest annotations and rest classes
This will work in the same delegate
Basically you can go with this approach. Actually i have that already implemented in php using zend framework.
You can create a class that holds all the api functions that you want to be exposed via rest or soap. And then you can make a php script that will grab the request and based on a parameter sent from the client will handle the request and dispatch it to a soap or rest service. Take a look at this code.
i have this function to check a parameter comming from the client, if it is rest then dispatch the request to the rest service, else , if it the parameter is soap then dispatch the request to the soap service , but notice that the Zend_Rest_Server and the Zend_Soap_Server classes are configured to use the same class ($controllerClassName) to handle the request.
So the same api(functionality) is exposed using rest and soap.
public function dispatch()
{
$this->preDispatch();
$include_file_path = sprintf(APPLICATION_PATH . "/modules/%s/controllers/%s.php", ucfirst($this->request->getModuleName()), ucfirst($this->request->getControllerName()));
require_once $include_file_path;
$controllerClassName = sprintf("%s_Controller", ucfirst($this->request->getControllerName()));
switch (strtolower($this->request->getServiceType())) {
case self::REST_SERVICE:
$r = $this->getRequest();
$server = new Rest_Server();
$server->setClass($controllerClassName);
$server->handleRequest($this->request);
break;
case self::SOAP_SERVICE:
if (array_key_exists('wsdl', $this->getRequest()->getQuery()) || array_key_exists('WSDL', $this->getRequest()->getQuery())) {
$auto = new Zend_Soap_AutoDiscover();
$auto->setClass($controllerClassName);
$auto->handle();
} elseif (count($this->getRequest()->getQuery()) == 0) {
$wsdl = sprintf('http://%s%s?wsdl', $this->getRequest()->getHttpHost(), $this->getRequest()->getPathInfo());
$soapServer = new Soap_Server($wsdl);
$soapServer->setClass($controllerClassName);
$soapServer->handle();
}
break;
default:
break;
}
$this->postDispatch();
}

How to version REST URIs

What is the best way to version REST URIs? Currently we have a version # in the URI itself, ie.
http://example.com/users/v4/1234/
for version 4 of this representation.
Does the version belong in the queryString? ie.
http://example.com/users/1234?version=4
Or is versioning best accomplished another way?
Do not version URLs, because ...
you break permalinks
The url changes will spread like a disease through your interface. What do you do with representations that have not changed but point to the representation that has? If you change the url, you break old clients. If you leave the url, your new clients may not work.
Versioning media types is a much more flexible solution.
Assuming that your resource is returning some variant of application/vnd.yourcompany.user+xml all you need to do is create support for a new application/vnd.yourcompany.userV2+xml media type and through the magic of content negotiation your v1 and v2 clients can co-exist peacefully.
In a RESTful interface, the closest thing you have to a contract is the definition of the media-types that are exchanged between the client and the server.
The URLs that the client uses to interact with the server should be provided by the server embedded in previously retrieved representations. The only URL that needs to be known by the client is the root URL of the interface. Adding version numbers to urls only has value if you construct urls on the client, which you are not suppose to do with a RESTful interface.
If you need to make a change to your media-types that will break your existing clients then create a new one and leave your urls alone!
And for those readers currently saying that this makes no sense if I am using application/xml and application/json as media-types. How are we supposed to version those? You're not. Those media-types are pretty much useless to a RESTful interface unless you parse them using code-download, at which point versioning is a moot point.
I would say making it part of the URI itself (option 1) is best because v4 identifies a different resource than v3. Query parameters like in your second option can be best used to pass-in additional (query) info related to the request, rather than the resource.
Ah, I'm putting my old grumpy hat on again.
From a ReST perspective, it doesn't matter at all. Not a sausage.
The client receives a URI it wants to follow, and treats it as an opaque string. Put whatever you want in it, the client has no knowledge of such a thing as a version identifier on it.
What the client knows is that it can process the media type, and I'll advise to follow Darrel's advice. Also I personally feel that needing to change the format used in a restful architecture 4 times should bring huge massive warning signs that you're doing something seriously wrong, and completely bypassing the need to design your media type for change resiliance.
But either way, the client can only process a document with a format it can understand, and follow links in it. It should know about the link relationships (the transitions). So what's in the URI is completely irrelevant.
I personally would vote for http://localhost/3f3405d5-5984-4683-bf26-aca186d21c04
A perfectly valid identifier that will prevent any further client developer or person touching the system to question if one should put v4 at the beginning or at the end of a URI (and I suggest that, from the server perspective, you shouldn't have 4 versions, but 4 media types).
You should NOT put the version in the URL, you should put the version in the Accept Header of the request - see my post on this thread:
Best practices for API versioning?
If you start sticking versions in the URL you end up with silly URLs like this:
http://company.com/api/v3.0/customer/123/v2.0/orders/4321/
And there are a bunch of other problems that creep in as well - see my blog:
http://thereisnorightway.blogspot.com/2011/02/versioning-and-types-in-resthttp-api.html
These (less-specific) SO questions about REST API versioning may be helpful:
Versioning RESTful services?
Best practices for web service REST API versioning
There are 4 different approaches to versioning the API:
Adding version to the URI path:
http://example.com/api/v1/foo
http://example.com/api/v2/foo
When you have breaking change, you must increment the version like: v1, v2, v3...
You can implement a controller in you code like this:
#RestController
public class FooVersioningController {
#GetMapping("v1/foo")
public FooV1 fooV1() {
return new FooV1("firstname lastname");
}
#GetMapping("v2/foo")
public FooV2 fooV2() {
return new FooV2(new Name("firstname", "lastname"));
}
Request parameter versioning:
http://example.com/api/v2/foo/param?version=1
http://example.com/api/v2/foo/param?version=2
The version parameter can be optional or required depending on how you want the API to be used.
The implementation can be similar to this:
#GetMapping(value = "/foo/param", params = "version=1")
public FooV1 paramV1() {
return new FooV1("firstname lastname");
}
#GetMapping(value = "/foo/param", params = "version=2")
public FooV2 paramV2() {
return new FooV2(new Name("firstname", "lastname"));
}
Passing a custom header:
http://localhost:8080/foo/produces
With header:
headers[Accept=application/vnd.company.app-v1+json]
or:
headers[Accept=application/vnd.company.app-v2+json]
Largest advantage of this scheme is mostly semantics: You aren’t cluttering the URI with anything to do with the versioning.
Possible implementation:
#GetMapping(value = "/foo/produces", produces = "application/vnd.company.app-v1+json")
public FooV1 producesV1() {
return new FooV1("firstname lastname");
}
#GetMapping(value = "/foo/produces", produces = "application/vnd.company.app-v2+json")
public FooV2 producesV2() {
return new FooV2(new Name("firstname", "lastname"));
}
Changing Hostnames or using API Gateways:
Essentially, you’re moving the API from one hostname to another. You might even just call this building a new API to the same resources.
Also,you can do this using API Gateways.
I wanted to create versioned APIs and I found this article very useful:
http://blog.steveklabnik.com/posts/2011-07-03-nobody-understands-rest-or-http
There is a small section on "I want my API to be versioned". I found it simple and easy to understand. The crux is to use Accept field in the header to pass version information.
If the REST services require authentication before use, you could easily associate the API key/token with an API version and do the routing internally. To use a new version of the API, a new API key could be required, linked to that version.
Unfortunately, this solution only works for auth-based APIs. However, it does keep versions out of the URIs.
If you use URIs for versioning, then the version number should be in the URI of the API root, so every resource identifier can include it.
Technically a REST API does not break by URL changes (the result of the uniform interface constraint). It breaks only when the related semantics (for example an API specific RDF vocab) changes in a non backward compatible way (rare). Currently a lot of ppl do not use links for navigation (HATEOAS constraint) and vocabs to annotate their REST responses (self-descriptive message constraint) that's why their clients break.
Custom MIME types and MIME type versioning does not help, because putting the related metadata and the structure of the representation into a short string does not work. Ofc. the metadata and the structure will frequently change, and so the version number too...
So to answer your question the best way to annotate your requests and responses with vocabs (Hydra, linked data) and forget versioning or use it only by non backward compatible vocab changes (for example if you want to replace a vocab with another one).
I'd include the version as an optional value at the end of the URI. This could be a suffix like /V4 or a query parameter like you've described. You might even redirect the /V4 to the query parameter so you support both variations.
I vote up for doing this in mime type but not in URL.
But the reason is not the same as other guys.
I think the URL should be unique (excepting those redirects) for locating the unique resource.
So, if you accept /v2.0 in URLs, why it is not /ver2.0 or /v2/ or /v2.0.0? Or even -alpha and -beta? (then it totally becomes the concept of semver)
So, the version in mime type is more acceptable than the URL.