Build an iOS app access only Drupal CMS site

Drupal is based on mysql, in the new version 7 it gives option to choose sqlite. Either way, connecting from iOS app directly to Drupal db is a problem.

Somebody posted mysql library for mac OS, even for iSO, but it’s not public API. Apple won’t like it.

Solution: RESTful service on Drupal

Installation process is painful, because the missing sypc.php can’t be done through Update management web interface module.

Turn on RESTful service, getting node/1 is not a problem, but I couldn’t make user/1 to work, later I realized it’s permission problem, had to grant ‘pull user profile’ right to anonymous user.

The official doc stated that RESTful comes with basic authentication sub module, but I couldn’t find it, the only one available in RESTful config panel is Session Authentication, which means admin must log in to be able to call user/1

Tried http://username:passwrod@mysite/test/user/1, and using code to pass credential, like this code in ruby,  no good.


uri = URI('http://test.site.com/drupal/rest/user/1.json')

req = Net::HTTP::Get.new(uri.request_uri)

req.basic_auth 'user', 'psw'

res = Net::HTTP.start(uri.host, uri.port) {|http|
http.request(req)
}
p res
puts res.body

It seems Drupal RESTful service is having problem in basic authentication. Or I just too dumb to figure it out.

My project doesn’t have a requirement to protect web content, which means those nodes should be only available to iOS client.

Work Around: Secure site module

One problem to fix is to apply patch for non-Apache-module mode php site, mine is CGI, adding

RewriteRule .* – [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]

to .htaccess, tah-dah, it works!

While the database setup in secure site module is still too messy to me, I just end up with setup a highly secured anonymous user for now. Anyway, content has been protected.

About testing Drual REST servcie

GET is fine, but http://test.site.com/drupal/rest/taxonomy_term/selectNodes is a POST only URI.

Test method 1: download Poster Firfox add-on, set Content Type to application/x-www-form-urlencoded, parameter to tid=1

To get json result, set headers to application/json.

Test method 2:

curl http://test.site.com/drupal/rest/taxonomy_term/selectNodes –form ‘tid=1’ -u user:pwd –header ‘Accept:application/xml’

Watch out, by default form-urlencoded is not checked after installation.

Passing json as request data is much easier.

curl http://test.site.com/drupal/rest/taxonomy_term/selectNodes –d {‘tid’:1} -u user:pwd –header ‘Accept:application/json’

doesn’t work for me, don’t know what missing.

Back to Session Authentication

According to this comment, to properly setup a session in RESTfule service is this:

  1. Get session id through an empty body POST to rest/system/connect, parse response to get session id. (Must set req[‘Accept’] = ‘application/json’ or xml if using ruby)
  2. POST to rest/user/login with parms like sessid=2c038ba6326f12f132502e98434857cc&username=<username>&password=<password>
  3. Parse body.

This works, but how to keeping session in the following rest request is not clear, more specific, how to pass sess id in request?

Here is another way based on Michael Cole’s comment, calling login directly, his example is saving session name/id in a cookie file, then passing it as session cookie in the following request. If actually can be passed as Cookie attribute in header.

Here is my explanation in ruby code,


  def login(username, psw)
    uri = URI("http://test.mysite.com/drupal/rest/u/login.json")

    req = Net::HTTP::Post.new(uri.request_uri)

    req.content_type = 'application/x-www-form-urlencoded'
    req.set_form_data("username" => username, 'password' => psw)
    #req['Accept'] = 'application/json'  #another style if url not end with .json

    res = Net::HTTP.start(uri.host, uri.port) {|http|
      http.request(req)
    }

    if Net::HTTPOK
       json = JSON(res.body)

      @session_id = json["sessid"]
      @session_name = json["session_name"]
    end
  end

  def get_post(id)
    uri = URI("http://test.mysite.com/drupal/rest/node/#{id}.json")

    req = Net::HTTP::Get.new(uri.request_uri)
    req["Cookie"] =  "#{@session_name}=#{@session_id}"
    res = Net::HTTP.start(uri.host, uri.port) {|http|

      http.request(req)
    }

    if Net::HTTPOK

       json = JSON(res.body)

      return json["body"]["und"][0]["safe_value"]
    end

  end

Best doc I found on drupal REST service.

Advertisements

3 thoughts on “Build an iOS app access only Drupal CMS site

  1. It is obvious that they will not be involved in something that they cannot
    ascertain whether it is right or wrong. While driving, the owner is also responsible for the security of the fellow passengers.

    At this time this has to be understood that the sum of insurance plan differ from time to time simply because insurance providers also have to
    abide by the state insurance plan legal guidelines.

  2. I used to be recommended this web site through my cousin.
    I’m not positive whether or not this post is written by him as nobody else understand such precise about my problem. You are amazing! Thank you!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s