I know this is probably a long-shot, but is it possible to use Siesta with a completely non-RESTful API? The API I have to work with (and is not in my control so sadly cannot change) requires every request to be a POST request regardless of whether it is purely retrieving data or not.
I've had a read through the question/answer here which gives me a glimmer of hope, however the big difference between that question and mine is the endpoints of each request. For the API I'm using, they're all the same :(
Every single request must POST to /api/api_post.php, and everything else is specified as a parameter supplied in the request.
Obviously I can roll my own request wrapper to handle this, but I'd love to be able to use some of the functionality provided by Siesta and not have to worry about all the annoyances of dealing with networking. Is there any way of doing this at all, or am I out of luck?
You can make your app work with an imaginary REST API, then transform that to non-restful requests underneath Siesta’s nose. (For example, GET /foo/3 might be transformed to POST /api/api_post.php with item=foo&id=3.) It’s a bit of a hassle, but it does get you the benefits of Siesta even for non-REST APIs.
There are two ways to implement this:
Use mutateRequests(…) to rewrite requests. This lets you arbitrarily alter the URLRequest before it’s sent.
Write your own NetworkingProvider. This is a bit more of a hassle, but gives more wholesale control of the rewriting. This approach might be more suitable if, for example, you need to rewrite responses as well, or if you have to turn one virtual request into multiple real ones.
More in the discussion here.
Related
I wanna fetch the content of a website. But to get the correct content, it is necessary to change a Input Html sroll field on the side?
Many idea how to manage with xcode?
Thanks a lot!!
Lars
If you want to retrieve the HTML that you get after filling in a HTML form, you have to identify precisely what the series of requests looks like to fetch the data. And be careful because it's often not as simple as just looking at the request that the HTML in question generates: unfortunately, it is sometimes a complex series of requests (e.g. retrieving the original HTML is often seamlessly retrieving some critical hidden form fields and/or cookies).
Bottom line, to reverse engineer the required HTTP requests, you often have to pour through HTML code and/or watch the requests with something like Charles. It often takes quite a bit of time to do this with complicated sites.
Before you invest a lot of time here, though, you should first see if the web site provider's Terms of Service permit such usage. They often strictly prohibit this sort of practice. It's much better to contact the web site provider and see if they provide a web service to retrieve the data. That's far easier and will result in a far more robust interface for your app.
But if you're forced programmatically parsing HTML, I'd refer you to How to Parse HTML on iOS on Ray Wenderlich's site.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking us to recommend or find a tool, library or favorite off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it.
Closed 8 years ago.
Improve this question
This seems naive to ask, but seriously I have not seen a resource which explains how to work with an API. The basics. More specifically the procedure to start-up with an API.
There are loads of things in the docs. But how to get it working with an RoR app. Like what variables to put in the db, in the attr-accessible. Or is it even required.
Then parsing it in models. Managing from the controllers and displaying/calling in the view. Dont get me wrong, I do know about RoR, I have made apps, but with API, seems confusing. Need to know all the basics.
Is there any resource which teaches to work with an API.
For my scenario, I want to work with a travel API. What should be the first procedure(after getting the API key).
How you work with an API is largely defined by how that API exposes itself, and what libraries of code you have to deal with it.
Many APIs are presented as HTTP endpoints that you can use CURL, OpenURI, HTTParty or something like that to consume the resource, or deal with the data sent to you, often as JSON or XML.
Here is a list of some of the more popular Ruby HTTP API client libraries at the Ruby-Toolbox.
Pick one of these and write some code that gets an endpoint of that API, then use that data to do whatever you need. Treat the API somewhat like a database.
Codeschool has a cool course that you can start with and do the first few levels for free here:
Surviving APIs with Rails
First, before choosing to work with an API or not, I highly suggest to try to work with REST API since these kind usually adhere to the same structure (there is even a book on REST API) and then you know what to expect.
Lets take a fictional Movie DB REST API example
so REST API is all about resources. Every movie can be created read, updating or deleted (CRUD).
so you know that you have these commands in your disposal - if you want to get a movie in your app you would use the read command that the api supplies. It usually looks like GET /movie/13 (HTTP GET request)
so in your app you would have to insert that line whereever you want it (perhaps in some panel where the user search for a movie and you access the movie DB to get the details of it
so you would have a
def movie_panel
#some stuff
#movie = MovieDB::get(movie_name)
end
so now you have the movie.. now what? parsing it is indeed annoying. luckly most API have gems you can use so they did the parsing for you. Here I used the fake gem MovieDB but if there is no gem you need to query the api yourself, which in this case I advise you to build your own gem, or atleast have a module with some classes and method to make life easier for you. something like
module MovieDB
class Movie
attr_accesor :name, :year, etc...
def initialize(movie_params)
#initizalize the movie attributes from a given movie params
#name = movie_params["name"]
etc..
end
end
end
so in this case you would have your own API wrapper to use. So once you are given the movie params from the external API you can do MovieDB::Movie.new(movie_params) and that will create a movie object that has method (that you need to write) for the functionality that you need in your code.
Inside that module you can handle everything about that API and abstract all that from the core of your app.
so to sum up -
REST API - easy, predictable, managable
non/rest api - make sure there is proper documentation
use what the api gives you as a resource, and ask yourself questions - what do I want from the API? what will I do with the resources (such as a movie, or a facebook page, or a tweet)? Does the API docs say its capable of doing what you want to do with the resource?
as documentation goes, you need to read it to understand what to do. No all docs are clear and not everything is clear on the first reading because you don't know where to start. So start at the beginning - why do you want to API? What does the API promise to do? You need to authenticate? Is there a tutorial? Has someone already made a gem for the API?
take some famous API's and not-so famous API as an example.
Facebook Graph API is very well documented. You know exactly what you get from each command and what to expect. You don't need to write it yourself, since Koala gem have you covered. On the other hand of the API rainbow, lies a Pinterest API, which you might wonder what's it for.. No one knows, because its barely useable, you need to get access to it, and even then its very limited. So if you want to plung in to the Pinterest API, make sure you understand what it gives you and what it doesn't (hint - it doesn't). That's true for every API where it has good docs or bad docs.
Good luck and might I suggest to read http://shop.oreilly.com/product/0636920028468.do and maybe this as well - https://github.com/interagent/http-api-design
Update with the actual API
ok so the api http://www.wego.com/api/flights/docs you wanted is documented quite well
the first thing it says is to get the API rate check
GET http://www.wego.com/api/flights/usage.html?format=json&apiKey=testAPIKey
so right here you can begin to structure your code. You need to save the apiKey somewhere and have a url prefilled with http://www.wego.com/api/flights/usage.html and the parameters are the format and the apiKey
you can create a helper method that does that.
def check_rate(format, apiKey)
...
end
inside you will need to send a request and get the response and parse it something like
uri = URI.parse(#url)
https = Net::HTTP.new(uri.host,uri.port)
req = Net::HTTP::Get.new(uri.path)
req.body = ["format=" + #format, "apiKey=" + #apikey]
res = https.request(req)
and that takes you forward one step. Take the result and parse it. Best in this case is to create a class for this kind of response and add methods such as rate_ok? and such. Basically a Class for each response and instantiate a class per response. The constructor of the class would parse the response and expose whatever attributes you need
I'm working on a collaborative document editing application where clients can open up a document, post edits via a webservice, and subscribe to updates made to the document using SignalR. I'm experimenting with my SignalR setup and can't quite get what I want.
My gut tells me that I should shoot for a setup where each document has an endpoint with a name like "subscribe", so the full path would be "/documents/1/subscribe" for document 1 and "/documents/2/subscribe" for document 2. However, as far as I can tell, SignalR wants me to have a single endpoint, and then manage which clients get updates either by using Groups or by managing the list of subscribers for a document in code myself and send out individual messages.
As a result I have two questions.
Is there a way to do what I want to do what I want to do with SignalR?
Is there a reason what I want to do is totally wrong headed and silly?
Aside from "dedicated", friendly looking URLs I don't really see any value to this vs. just using groups. In fact, the only thing I could see it doing is adding more overhead because of the way the message bus internals of SignalR work with respect to scale.
If you did want to try this, the base thing you'd need to figure out would be registering routes on the fly per document, which, as Phil Haack's RouteMagic has done for MVC, I suppose it might be possible for SignalR route configurations as well.
You can give someone an url with get:
http://myserver.com/?var=val
But what to do with POST method ? I know that the program I put url into must support this, I do not know any browser that can (maybe with plugin possible), but is there widely accepted syntax to do it, for example I came up with this:
http://myserver.com/<var=val>
or maybe:
http://myserver.com/??var=val
http://myserver.com/?!var=val
http://myserver.com/!!var=val
http://myserver.com/!var=val
etc...
I'm writing a tool to do it , and I wonder if I must think on my own just like first guy who created e-mail and out of the air conceived # character since it was rarely used then...
The idea is that some services use post data and there is no way to send someone link to resource there. And yes I know that when there is post data that resource is not meant to be such easy passeable to people... but wait since when author of a website has to have power over what I can and can't do with his service.
You'd better introduce a separate argument for passing POST data to your tool. Mixing it together with URL would just cause confusion among your users. Remember that POST data be quite large, so you'd end up introducing features like loading POST data (or a value of an individual variable) from a file anyway.
I'm trying to delete blobs in an mvc 3 application that uses azure storage.
I'm trying to pass the Uri of the blob which will be deleted to the controller, however an error is thrown:
A potentially dangerous Request.Path value was detected from the client (:)
I think this is from the https: part of the Uri and I need to parse it out, however I'm not sure how to do that. I'm wondering how to fix this error.
Is there a more graceful way to delete a blob from storage?
You must properly URL encode your urls. Here's an example of a badly encoded url:
http://foo.com/controller/action?param=http://bar.com
Here's how it should look like:
http://foo.com/controller/action?param=http%3A%2F%2Fbar.com
Or maybe you are having an url of the form:
http://foo.com/controller/action/https://bar.com
which is even worse. If you want to use special characters in the Path portion of an URL you might find the following blog post useful.
If you want unsecure content to get through then you can add [ValidateInput(false)] to your action - however, this is opening up something that is there for your security - so only do this if you are sure you're code is secure - see first answer in A potentially dangerous Request.Form value was detected from the client
I was able to fix it and I want to summarize the solution, since it requires bit from the other two answers and bits mostly from the Scott Hanselman Blog post.
You need to do a few things to make this work:
Put the [ValidateInput(false)] on your action method.
Make sure your Url is properly encoded (an example is given in the above post) which is done when you use the blobVariableName.Uri.AbsoluteUri as the string to pass from your view to your controller, so you shouldn't have to do anything there.
Make your query string looks like
http://site/controller/action?blobid=http%3A%2F%2F... and NOT http://site/controller/action/http%3A%2F%2F... the latter won't work!
On a side note, since I started, our functional requirements changed and now were storing information about each blob in the database, which allows me to pass parameters other than the blob's uri, which seems like a much safer way to play it.
A great deal of the community appears to be in agreement that it is a bad idea to pass uri's and to open up your application as to allow you to do so.