Re: [RavenDB] RavenDB and PHP

755 views
Skip to first unread message

Fitzchak Yitzchaki

unread,
Sep 19, 2012, 3:22:28 AM9/19/12
to rav...@googlegroups.com
You could use RavenDB over HTTP directly from your application. No need to use cURL.
The best documentation is the HTTP API documentation of RavenDB.

On Wed, Sep 19, 2012 at 10:05 AM, mice-pace <danie...@aabrothers.com.au> wrote:
I have a reasonable bit of programming experience but I'm still very new to RavenDB, and since much of my programming experience is in PHP, I thought 'Why not get a handle on this NoSQL stuff by integrating it into what you know?'

I'm wondering how many other people are trying to do this, information about it is quite difficult to find (Mostly because of how difficult it is to get Google to tell the difference between 'POST requests' and 'Forum posts'... not to mention any page with a php url shows up ;-) )

Single page requests are easy (file_get_contents... it's all in the url afterall) but my first time trying to do a POST to query for multiple documents resulted in quite a bit of head scratching, research and then finally producing... something that didn't work :-P

So if anyone's got any advice I'd love to hear it, links to examples or tutorials would be brilliant, but if not... hey, i might be able to help expand the Knowledge base a tiny bit.



My Understanding so far (presumably wrong) is:

> curl -X POST http://localhost:8080/queries -d "['users/ayende','users/oren']"

should equate to something like:

  $json = "
['users/ayende','users/oren']";
 
  $opts = array(
    'http' => array(
      'method' => 'POST',
      'header' => 'Accept: application/json',
      'content' => $json
    )
  );
 
  $context = stream_context_create($opts);
  $response = file_get_contents("
http://localhost:8080/queries", false, $context);


...Or are streams different? If so am I going to have to get the cURL library for PHP then?


Ryan Heath

unread,
Sep 19, 2012, 3:56:12 AM9/19/12
to rav...@googlegroups.com
You probably want to look at this?

I have done very little with php but that post helped me back in the days ;)

// Ryan

mice-pace

unread,
Sep 19, 2012, 8:22:08 PM9/19/12
to rav...@googlegroups.com
You could use RavenDB over HTTP directly from your application. No need to use cURL.
The best documentation is the HTTP API documentation of RavenDB.

That as always, has been my starting point. The HTTP API documentation tells me *what* I need to do, but the implementation on *how* to do so changes between each programming language a little.



On Wednesday, September 19, 2012 5:56:14 PM UTC+10, Ryan Heath wrote:
You probably want to look at this?

I have done very little with php but that post helped me back in the days ;)

That's brilliant. Very informative. I was halfway to doing this already since i was already generating the Stream Context, but this way lets me catch a lot of potential problems file_get_contents isn't meant to cover

Interestingly, this gives me the same error as my previous attempt '401 Unauthorized'... I'll do a little digging, but if someone beats me to the answer and posts it here i won't be unhappy :-)

Troy

unread,
Sep 19, 2012, 8:37:47 PM9/19/12
to rav...@googlegroups.com
If you are not doing any authorization, perhaps you need to set: <add key="Raven/AnonymousAccess" value="All"/>

Troy

unread,
Sep 19, 2012, 8:38:56 PM9/19/12
to rav...@googlegroups.com
Keep in mind, that opens you up completely to anyone querying Raven.

mice-pace

unread,
Sep 19, 2012, 8:49:27 PM9/19/12
to rav...@googlegroups.com
If you are not doing any authorization, perhaps you need to set: <add key="Raven/AnonymousAccess" value="All"/>
Haha, you beat me to it! :-D (Literally as i was typing this I got the email)

A quick glance found me a potential explanation, this guy is also getting 401's:

http://stackoverflow.com/questions/12488234/how-to-delete-a-ravendb-database-with-raven-client-lightweight/12490649#12490649

He needed to provide credentials, I don't think I am either... the question becomes now, how do I add that to part of my request in PHP?


Keep in mind, that opens you up completely to anyone querying Raven.

Yeah I Know :-| That's why I'd rather figure out how to put the credentials in now, rather than make something work and risk forgetting about that sticking point. Thanks Troy :-)

mice-pace

unread,
Sep 19, 2012, 9:27:49 PM9/19/12
to rav...@googlegroups.com
Just a note for work in progress (I could wait until I've tried it, but I thought I'd let anyone watching this thread know now, in case they are struggling with this too)

http://en.wikipedia.org/wiki/Basic_access_authentication

Describes the process, ending up with something like:

if the user agent uses 'Aladin' as the username and 'sesam open' as the password then the header is formed as follows:
Authorization: Basic QWxhZGluOnNlc2FtIG9wZW4=

If I'm on the wrong path someone let me know, and if I'm not I'll post some working code later today hopefully

mice-pace

unread,
Sep 19, 2012, 11:19:26 PM9/19/12
to rav...@googlegroups.com
Yup, I'm on the wrong path...

Authorization: Basic

RavenDB doesn't use Basic Authentication... It uses Windows Authentication. Hmm.

What are my options here?
  • Find some way to make PHP use Windows Authentication?
  • Find some way to make Raven accept Basic Authentication?
  • Disable Authentication on Raven but make it check where the Request is coming from? (since the PHP should only be running from one location)

Does anyone know which of these are even possible and possibly how they are done? :-\

codin...@googlemail.com

unread,
Sep 20, 2012, 12:23:29 AM9/20/12
to rav...@googlegroups.com
Can you use the oauth provider in rdb?

Sent from my iPhone

Mauro Servienti

unread,
Sep 20, 2012, 12:30:49 AM9/20/12
to rav...@googlegroups.com

What is the problem in using Windows Authentication?

RavenDB is running on Windows (I guess) thus you only need to specify in the connection string you are using to connect to the server a valid Windows user & password that the server can use to authenticate the incoming request.

 

.m

mice-pace

unread,
Sep 20, 2012, 12:42:00 AM9/20/12
to rav...@googlegroups.com

you only need to specify in the connection string you are using

The problem is this is PHP, not .NET... The important difference here being that because this is not .NET we are forced to use the HTTP API, and I haven't seen anything at all about Connection-strings in the HTTP API documentation, but Hey, if you find something I missed you'd be making my day :-) [http://ravendb.net/docs/http-api]


Can you use the oauth provider in rdb?

Yeee-es? I think so. PHP appears to have a library for OAuth... I wonder if it will be a pain to set up. How does OAuth work?

codin...@googlemail.com

unread,
Sep 20, 2012, 12:53:55 AM9/20/12
to rav...@googlegroups.com
How does OAuth work?

You have some reading to do. Maybe use the .Net stuff as a starting point example?

Sent from my iPhone

Oren Eini (Ayende Rahien)

unread,
Sep 20, 2012, 3:00:33 AM9/20/12
to rav...@googlegroups.com
In RavenDB, you would need to do the following:

1) Make a request, if it is 401, you will have a OAuth-Source header that point you to a url.
2) You make authenticate against that url, and it sends you a response back. (usually it is using basic auth).
3) You use the response in the next request as the auth header.

You can see how this works here:

mice-pace

unread,
Sep 20, 2012, 10:26:06 PM9/20/12
to rav...@googlegroups.com
That Javascript client has been fairly instructive, thanks Oren! I've adapted most of the appropriate section of that so far, but i can't be sure i'm sending it the right user/password combination... Why?

In order to add a user we can use the following code:

using(var session = documentStore.OpenSession())
{
session.Store(new AuthenticationUser
{
Name = "Ayende",
Id = "Raven/Users/Ayende",
AllowedDatabases = new[] {"*"}
}.SetPassword("abc"));
session.SaveChanges();
}

If no users are found on the database a user "admin" will be created with an auto generated password. This data can be viewed in the "authentication.config" file.


That "following code" ^^^ ...I'm not sure where to run it. Either it's .NET code or I just don't know the guts of RavenDB well enough. That might be fine if i could find "authentication.config", but when I search for files with 'authentication' in the name all i find are the bundle DLLs :-\

Oren Eini (Ayende Rahien)

unread,
Sep 21, 2012, 7:29:42 AM9/21/12
to rav...@googlegroups.com
This is saving a new document to the database with the given structure.
You can do the same by calling PUT /docs/Raven/Users/Ayende with the document content.

Did you add the authentication dll to the plugins directory and set the auth mode to be oauth?

mice-pace

unread,
Sep 23, 2012, 10:39:19 PM9/23/12
to rav...@googlegroups.com
I certainly did, Thanks Oren. And I'm pretty sure that's working because when i make a POST request i get the following set of headers:

HTTP/1.1 401 Unauthorized 
WWW-Authenticate: Bearer realm="Raven", error="invalid_request",error_description="The access token is required" 
Server: Microsoft-HTTPAPI/1.0 
OAuth-Source: http://vserver1:8080/OAuth/AccessToken 
Date: Mon, 24 Sep 2012 00:42:55 GMT 
Connection: close 
Content-Length: 0
Implying that it is using OAuth, i haven't provided the token, and it is graciously telling me where i can go to get one.


I tried adding the following document from inside the web interface (hoping the above code would make Json like this, but pretty sure it's not right )
{
        "Name":"Ayende",
        "Id":"Raven/Users/Ayende",
"Password":"123",
        "AllowedDatabases":[{"*"}]
    }

Mostly because I can't access it at  http://MyServer:Port/docs/Raven/Users/Ayende... Which is probably why my attempt to get a token keep failing and telling me where to go :-p
 

Oren Eini (Ayende Rahien)

unread,
Sep 24, 2012, 3:59:16 AM9/24/12
to rav...@googlegroups.com
You now need to make an authenticated request here:   http://vserver1:8080/OAuth/AccessToken  

After which you will have the token to retry

mice-pace

unread,
Sep 24, 2012, 11:20:57 PM9/24/12
to rav...@googlegroups.com
Mmhmm, i had figured as much (but only realised now i hadn't said it) since that example you gave me was quite good. I think the problem i'm having is authenticating with that particular page;

PHP:
//After making a normal request which failed

foreach ($http_response_header as $headerItem)
    {
      if (substr($headerItem, 0, 5) == 'OAuth') $authURL = substr($headerItem, (strpos($headerItem, ":")+1));
      if (substr($headerItem, 0, 16) == 'WWW-Authenticate') $auth = true;
      if (($authURL != "") && ($auth == true)) break;
    }
//Check that it is asking for authentication, if so, grab the URL we need to go to.

if (($authURL == "") && ($auth == false)) throw new Exception("Problem with $url, $php_errormsg");
    else 
    {
    $authPass = base64_encode($RAVEN_USER.":".$RAVEN_PASS);
    //Username and password... in this case "Ayende:123"

    $opts = array(
        'http' => array(
         'method' => 'POST',
         'header' => 'Content-type: application/x-www-form-urlencoded, Accept: application/json, Authorization: Basic '.$authPass,
         'content' => $json
         )
      );
      
      $context = stream_context_create($opts);
      
      $fp = @fopen($authURL, 'rb', false, $context);
      
      error_log("Authentication Response is... ".print_r($http_response_header, true));
      die;
    }

The Response is not giving me a token, it's still telling me to authenticate.

My best guess is either the format of the request to that page (POST) is wrong, or the Json code I used to add an authentication/user was wrong... if the json was right should I be able to find the result in the list of docs? 


Oren Eini (Ayende Rahien)

unread,
Sep 25, 2012, 5:28:06 AM9/25/12
to rav...@googlegroups.com
Can you show me what this looks like on the wire, a Fiddler capture of your php code talking to raven would be very helpful.

Daniel Vida - AABrothers

unread,
Sep 25, 2012, 5:52:15 AM9/25/12
to rav...@googlegroups.com

I can't make any promises, I've used fiddler briefly but not had a lot of luck with it, but I will try tomorrow and hopefully I will have something useful for you :-)

JBA

unread,
Feb 22, 2013, 2:50:27 PM2/22/13
to rav...@googlegroups.com
Did this ever get resolved?  I'm struggling with PHP authentication to Raven and if you were successful in getting this to work,  I'd be very grateful if you could post a working code snippet or a link to your fiddler.  

I know this is a 5 month old thread, but this thread is the top google result when searching "ravendb php file_get_contents", so a final working resolution might be helpful to future PHP developers trying to connect to raven as well.

Thanks!

Khalid Abuhakmeh

unread,
Feb 22, 2013, 7:04:36 PM2/22/13
to rav...@googlegroups.com
He could also setup an API key, it is in the system database.

mice-pace

unread,
Jun 20, 2013, 1:24:54 AM6/20/13
to rav...@googlegroups.com
Hello again!

I recently updated Raven (after putting this issue asside for ages) to pleasantly discover that setting up for OAuth should be much easier now... between these two:

http://jason.pettys.name/2013/05/12/securely-accessing-ravendb-ravenhq-over-http/

http://ravendb.net/docs/2.0/server/authentication?version=2.0

And the previous stuff in this thread, i now have a good idea what I've got to do... My problem is since Upgrading i no longer get the appropriate header [OAuth-Source: http://vserver1:8080/OAuth/AccessToken] with my 401's

Instead I'm getting:

HTTP/1.1 401 Unauthorized
Content-Length: 0
Server: Microsoft-HTTPAPI/1.0
WWW-Authenticate: Negotiate
www-Authenticate: NTLM

Date: Mon, 24 Sep 2012 00:42:55 GMT
Connection: close

Is there a way to disable Windows authentication, or to tell Raven to use OAuth by default

Oren Eini (Ayende Rahien)

unread,
Jun 20, 2013, 1:43:51 AM6/20/13
to ravendb
Hm, you need to send a request with Has-Api-Key: true header



--
You received this message because you are subscribed to the Google Groups "ravendb" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ravendb+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

mice-pace

unread,
Jun 20, 2013, 2:06:08 AM6/20/13
to rav...@googlegroups.com
Brilliant! Just got another OAuth-Source header on cURL... Not on PHP yet, but with any luck that was the only piece i was missing.

If i get this going all the way on PHP i will post it as a Function, so people will be able to use it by just passing it a few variables.

mice-pace

unread,
Jun 20, 2013, 3:07:34 AM6/20/13
to rav...@googlegroups.com
Hmm. Not yet. I can locate and copy the OAuth-Source from the headers now when i get a 412 (Precondition failed - invalid request: access token is required) but when i send it the 'Api-Key' with a 'grant_type' of client_credentials i get a 400 error (Bad Request)

Here's the snippet of the code that's doing it... just after we failed because we need a token

      for ($count=0; $count<$noOfHeaders; $count++){
        
        $header = $http_response_header[$count];
        if (strpos($header, "OAuth-Source")!==false){
          $auth_url = substr($header, 14);
          error_log("'".$auth_url."'");
          break;
        }
        
      }
      if ($auth_url !== ""){
        
        error_log("getting token");
        $auth_opts = array(
          'http' => array(
            'method' => 'GET',
            'header' => 'Api-Key: '.$RAVEN_KEY.'\r\ngrant_type: client_credentials\r\n',
            'content' => ""
          )
        );
        
        $auth_context = stream_context_create($auth_opts);
        $fp = @fopen($auth_url, 'rb', false, $auth_context);

Finds the OAuth-Source from the headers and sends a GET request to that url with this header:

Api-Key: apikeyname/6UGgPHZ1F1A
grant_type: client_credentials

Oren Eini (Ayende Rahien)

unread,
Jun 20, 2013, 3:19:27 AM6/20/13
to ravendb
This is the implementation that you need to copy

This is a bit more involved & secured than what we previously had


Reply all
Reply to author
Forward
0 new messages