I play with Rook (https://portal.aviso.io/#/document/open-source/rook/Current) for Clojure based REST services.
While the general layout of Rook is quite clear (implementing Verbs for different interfaces) I am not so clear if I grokked Rook's approach for POST bodies. I.e. implementing a POST, I can access the request body, yet I wonder if this is the intended way:
(defn create
[ ^:request requ]
(let [request-body (slurp (:body requ))]
...
))
As long as you are using the standard middleware, the contents of a body request is available deserialized as the value of the :body-params key of the request map.
Related
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")
Can you please confirm if below implementation for PUT vs POST defies REST principle:
If a resource was created via POST, allow update to the resource via POST (else return 412 error)
If the resource was created via PUT, allow update to resource via PUT (else return 412 error)
I understand both PUT and POST can be used to create a resource. What I think is not right in this case is dependency on how resource was created (PUT/ POST) and takes action based on it. Can you point me to the RFC?
If a resource was created via POST, allow update to the resource via POST (else return 412 error)
If the resource was created via PUT, allow update to resource via PUT (else return 412 error)
Can you please confirm if below implementation for PUT vs POST defies REST principle
It's probably wrong, but not necessarily so.
In particular, PUT in HTTP has very specific semantics
The PUT method requests that the state of the target resource be created or replaced with the state defined by the representation enclosed in the request message payload.
In other words, PUT is appropriate for replace, but it is not appropriate for modify.
So what your guideline is actually implying is that if you create a resource via a PUT of its representation, then all subsequent changes to that resource must also be complete replacements.
It's not obvious to me that's a good idea, and there is nothing in HTTP that requires you to be so strict; but it's certainly possible that your guideline authors had some bad experiences, which may be specific to the circumstances in which those guidelines apply.
The notes about using 412 response is... odd. Again, in HTTP, 412 has a very specific meaning; and that meaning is not related to the method used in the request. Using a conditional request to ensure that your edit doesn't conflict with another is good idea.
But if somebody has done a POST where they should do a PUT, or vice versa, then the correct status code to return in that case is 405.
The 405 (Method Not Allowed) status code indicates that the method received in the request-line is known by the origin server but not supported by the target resource. The origin server MUST generate an Allow header field in a 405 response containing a list of the target resource's currently supported methods.
Can you point me to the RFC?
There is no "RFC" for REST; it's not a standard, in that sense. REST is just a set of architectural constraints discovered by Roy T. Fielding during the early web standardization process. The appropriate reference is Chapter 5 of Fielding's thesis.
HTTP as a standard does (for the most part) use an architecture that satisfies the REST constraints. As of late 2016, the standard is documented by RFCs 7230-7235 inclusive.
A RESTful URL typically points to either a collection or an element.
A collection is typically denoted in plural and could look like this:
https://www.example.com/api/v1/cars
An element is typically adressed with its identifier and could look like this:
https://www.example.com/api/v1/cars/17
Collections can be children to elements:
<code>https://www.example.com/api/v1/workplaces/22/rooms</code>
Doing a POST to a collection usually means creating an element in the collection and the new element is typically returned with the response. The server would be responsible for creating the URI for the newly created element. It is the recommended "RESTful" way of creating elements.
Doing a POST to a element is not often used (and discouraged) as that would mean the client would be the one assigning the identifier. If used, most often, it means that you treat the element as a collection in itself and create a new element within it.
Doing a PUT to a collection is perfectly valid "RESTfulness" but would typically mean replacing the entire collection.
Doing a PUT to an element is common and typically means replacing the entire element, meaning that the entire element should be passed along in the request body. Some argue it is fine for the element to be created if it does not exist (but I would argue it being a bad request).
Doing a PATCH to an element typically means updating the element. The fields that should be updated are the only fields necessary in the request body.
I've never stumbled on doing a PATCH to a collection and would probably recommend against it.
I would like to modify an url parameter /resource/{VaRiAbLe} in an API gateway to S3 mapping so that it actually points to /my-bucket/{variable}. That is, it accepts mixed-case input, and maps it to a lower-case name. Mapping path variables is relatively simple enough to S3 integrations, but I can't seem to get a lower-case mapping working.
Reading through the documentation for mapping parameters, it looks like the path parameters are simple string values (and not templated values), and so defining a mapping as method.request.path.variable.toLowerCase() won't work.
Does anyone have any ideas how to implement this mapping?
Map path variables to a JSON body, and then call another API method that actually does the S3 call?
Bite the bullet, and implement a Lambda function to do the S3 get for me?
Find another api method for S3 that accepts a JSON body that I can use to get the data?
Update using Orchestrated calls
Following the info from Jack, I figured I should try doing the orchestrated call, since the traffic volume is low enough that I am sure that I won't be able to keep the lambda hot.
As a proof of concept, I added two methods to my resource (sitting at /resource/{variable} - GET and POST. The GET method chains to the POST, which does the actual retrieving of the data.
POST method configuration
This is a vanilla S3 proxying method, where you set the URL Path parameter for {variable} to be method.request.body.variable.
GET method configuration
This is a HTTPS proxying method. You'll need an URL for the POST method, so you'll need to deploy the API to get the URL. The only other configuration needed here is a body mapping template with content like:
{
"variable" : "$input.params('variable').toLowerCase()",
"something" : "$input.params('something')"
}
This should be enough to get this working.
The downside to this looks to be that I'm adding an extra method (POST) to my API for that resource that could confuse consumers of the API. I think it should be possible to make the POST on the /resource resource, which would at least make a bit more sense from an API design standpoint.
Depending on how frequently this API will be called, I'd either go with the Lambda proxy or chaining two API Gateway methods together. If the API is called frequently enough to keep a Lambda function warm (say once a minute), then go with Lambda. If not, go with the orchestrated API call.
The orchestrated API call would be interesting, I'd be happy to help with that if you have questions.
As far as I know the only S3 API for getting object data is the GET that is documented in their API reference.
Im developeing a RESTful Service in which Processes can be executed and proivde a resulting calculation. For this i have modeled the process itself as a Resource (Example: /processes/translate). I want to execute the process by sending a GET request with appended Input Parameter as Query Parameter (Example: /processes/translate?input1=xxxx&input2=xxxxx).
Each process has different Input Parameter which are defined during the process creation in the backend. My Question is how should i document or describe which inputs are needed to execute a process in machine readable form. For Example in XML.
Until now ive integrated atom:link elements in the Representation. i thought that maybe including XFORM could be a soluttion?
Best Regards
Andre
I would not model this with a GET. While it's the easier solution, it's also (IMO) the least RESTful. I would have clients POST a document describing what they want you to translate and your service sends them back a URI where their answer can be found (some translations might take a while).
Example (ommiting a lot of HTTP headers/context)
POST /processes/translate
Content-Type: application/xml
...
<translation-request>
<input1 type="type1">....</input1>
<input2 type="type5">....</input2>
</translation-request>
Response:
200 OK
Content-Location: /processes/translate/jobs/1234
....
That's always an interesting question. We have a project called RESTx (http://restx.org), with which you can create RESTful web services very easily. You can write custom component code in either Java or Python and then create RESTful resources by sending parameter sets to the server, which are then stored. Each parameter set gets its own URI, though, so you can always just run the code with those parameters by accessing the new parameter set's URI.
Importantly, the entire RESTful API, is automatically created. RESTx examines the component code and then assembles the API description. We decided to describe parameters in a way that is human as well as machine readable. You can see examples of what that looks like in a browser or in plain JSON.
I'm the lead developer on that, so please feel free to contact me about any questions you might have.
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.