Basic usage of Public REST API (sync gateway)

Hi there, I’m new to Couchbase and am trying to get some of the basics down. I’ve been able to mess with the todo lite app hooked up to a sync gateway and can see my created docs on the iPhone get inserted in the Couchbase server (through the sync gateway).

I wanted to now learn a little more about how to use the REST API and am getting a little stuck, or perhaps just a little confused. So I’m on the local server where I have both the sync gateway and the Couchbase database. I navigate to the Public REST API page for the sync gateway (https://developer.couchbase.com/documentation/mobile/current/references/sync-gateway/rest-api/index.html#/database) and wanted to try two different things.

  1. Getting basic meta-information about the server. When I click on the “Try it out!” button, I receive “error”:“no response from server” in the response headers section. I noticed that the request URL is “https://localhost/4984/”. Is that supposed to be “https” and not “http”? There’s no option for this REST API so I know I’m not messing up on the request.

  2. Manually adding a document to the todo database. I’m using the database operations with POST /{db}/_bulk_docs. Again, I’m putting in “todo” as the database name and entering a very basic JSON document. Like the above point #1, I see the URL formatted as “https” instead of “http” and I’m not receiving any response.

I did add the CORS section to the config file and restarted Couchbase.

Any thoughts or explanation would be much appreciated. I spent over an hour trying to search through the forums to find actual examples but I haven’t had any luck with that.

Thanks,
David

FYI
https://blog.couchbase.com/managing-rest-apis-swagger-video/
I think the document just generate curl command for you.
you should run the command on your local machine.

What error do you see when you run the curl command directly from command line ? It is likely that you are attempting https connection when you don’t have SSL enabled on localhost. Retry the request with http and see what you get.
You may also checkout the postman for querying the Sync Gateway . Here is a starting point- https://blog.couchbase.com/querying-couchbase-sync-gateway-with-postman/

Hi Atom/Priya, yeah, it turned out to be the SSL thing. I was able to configure that properly and when I re-ran a few of the POST from the online documentation, it worked. Thanks for posting that blog, which showed how to get that set up.

Priya, so if I need to load 300 or so initial documents to the Couchbase server, do I just copy/paste those into the BulkDocsBody window of the bulk docs POST method (/{db}/_bulk_docs) in the online documentation?

David

Yes, that should do it - make sure you specify it in the right JSON format as specified in the documentation

 {
      "docs": [
        {}
      ],
      "new_edits": true
    }

Atom/Priya, just a quick follow up question on this. So I enabled SSL and can see when the app connects with the sync gateway, but any data that I added to the app is not propagated to the Couchbase server. The only thing that changed was that I installed the SSL on the localhost and then switched the app gateway string from “http://xxx.xxx.xxx.xxx:4984/todo/” to “https://xxx.xxx.xxx.xxx:4984/todo/”. I’m guessing I am missing something else that must be changed when I installed SSL. Do you have any quick ideas on that? I tried looking around in the documentation but wasn’t able to find anything.

Thanks,
David

So the public REST API call to the same endpoint works ?
Couple of things

  • Can you double check replication is running (not stopped state).
  • Can you compare the document that you added directly via REST API with the one via the app. Basically I want to check if your Sync function is not rejecting the document from the app for any reason
  • Couchbase Lite console logs : Turn on verbose logging on the app to get better insight into what may be going on - https://developer.couchbase.com/documentation/mobile/1.4/guides/couchbase-lite/native-api/manager/index.html
  • What do the Sync Gateway logs say ? (are the documents even hitting the sync gateway)

I will try to get the logging data. However, when I switch the gateway string back to the one without the “https” and then remove the two .pem lines from the config file and restart the sync gateway, the data on my iPhone gets pushed up to Couchbase as soon as I fire up the app. I know that because I saw a whole bunch of records all of a sudden get inserted in the bucket, which I queried and confirmed. When I turn on the logging, where do I go to see the logs?

Thanks,
David

Ok, so when enable logging I see a lot of information in the debugger window. Seems like these lines are indicative of the problem:

2017-06-01 11:05:43.507597-0500 myLocTrack[27464:14383265] WARNING: CouchbaseLite: SSL server <xxx.xxx.xxx.xxx> not trusted; cert chain follows: {at CBLWarnUntrustedCert:294}

2017-06-01 11:05:43.507995-0500 myLocTrack[27464:14383265] WARNING: David {at CBLWarnUntrustedCert:299}

Back to my original question, after installing the SSL on the sync gateway and switching the gateway string, there still must be something else I must have to do on the app side. I’m using Swift 3 in Xcode 8.3.2.

David

Edit: After re-reading the SSL blog, I’m thinking this problem has something to do with the created certificate. Here’s a snippet from the blog:

Creating your own self-signed certificate

Unlike a CA-signed cert, a self-signed cert isn’t intrinsically trustworthy: a client can’t tell who you are by examining the cert, because no recognized authority has vouched for it. But a self-signed cert is still unique (only you, as the holder of the private key, can operate a server using that cert), and it still allows the connection to be encrypted.

It’s easy to create a self-signed certificate using the openssl command-line tool and these directions. In a nutshell, you just need to run these commands:

$ openssl genrsa -out privkey.pem 2048
$ openssl req -new -x509 -sha256 -key privkey.pem -out cert.pem -days 1095

The second command is interactive and will ask you for information like country and city name that goes into the X.509 certificate. You can put whatever you want there; the only important part is the field Common Name (e.g. server FQDN or YOUR name) which needs to be the exact hostname that clients will reach your server at. The client will verify that this name matches the hostname in the URL it’s trying to access, and will reject the connection if it doesn’t.

In the last instruction, I used my name in the Common Name field, as I don’t have a URL and only am using an IP address. Might this be the problem?

You can add the self-signed cert to the set of trusted certs to be used by the OS via
CBLReplication.setAnchorCerts(certs: [Any]?, onlyThese: Bool?)

/** Adds additional SSL root certificates to be trusted by the replicator, or entirely overrides the
OS’s default list of trusted root certs.
@param certs An array of SecCertificateRefs of root certs that should be trusted. Most often
these will be self-signed certs, but they might also be the roots of nonstandard CAs.
@param onlyThese If NO, the given certs are appended to the system’s built-in list of trusted
root certs; if YES, it replaces them (so only the given certs will be trusted.) */

Hi Priya, this is like an onion, lol.

Ok, so this explains how to get the DER format file:

Then this explains how to create an array using the DER file (swapping the constant “data” with the name of the DER file I created):

In the above example (thanks to Ian), where would it be best to place this code? Perhaps in AppDelegate?

Thanks,
David

Hey,
Actually, this is how you would handle certificate pinning on iOS and how you deal with self signed server certs in general - so in that sense, this is not unique to couchbase lite . In production, you would likely have a cert issued by a trusted CA - so you wouldn’t have to do this (al though you could to avoid MITM attacks)
As for your question : You would do this wherever you create your replicators. If you are setting up your replicators in your AppDelegate, then that’s where you’d call the setAnchorCert. My personal preference is to have a separate “CBLDatabaseManager” singleton that handles core CBL database management stuff . An an example : https://github.com/couchbaselabs/couchbase-mobile-ios-app-extension/blob/master/CBLiteAppExtension/DatabaseManager.swift

Thanks for the follow up. Is there a way to tell whether the setAnchorCerts worked? It does get through that line, but I’m still getting the same WARNING error message that I have referenced above. Not sure if this matters, but I did have to rename cert.cer to cert.der in order to get the following to work:

let certificateFileName = "cert"
let certificatePath = Bundle.main.path(forResource: certificateFileName, ofType: “der”)
let certificateData = NSData(contentsOfFile: certificatePath!)
let certificate = SecCertificateCreateWithData(nil, certificateData!)
CBLReplication.setAnchorCerts([certificate as AnyObject], onlyThese: false)

I did read somewhere that the name has to be an exact match, but I’m not entirely clear on what has to match with what. When running the function to create the .pem, there was an interactive line where I put in my full name, but I do not recall have to retype that name elsewhere.

David

Hey- So is replication working? If not, then it means that the cert verification did not go through. I did a quick setup with https on localhost, I have the Common Name in my self signed cert as “localhost”. I would recommend that you regenerate the cert using “localhost” as Common name so that way matches the local host that client is connecting to. Then try again.

In my setup, I have the .cer file bundled in my app .I did not have to convert to .der. This is my code snippet

if let pathToCert = Bundle.main.path(forResource: "cert", ofType: "cer") {
        
            if let localCertificate:NSData = NSData(contentsOfFile: pathToCert) {
                let certificate =
                    SecCertificateCreateWithData(nil, localCertificate)     
                CBLReplication.setAnchorCerts([certificate], onlyThese: false)
            }
        }

I think I will write a blog post on this shortly to clarify things …

Thanks for the snippet and I was able to generate a new cert and keep the extension cer.

I’m still getting that same error, but I think it might have to do with the fact that my Couchbase server is not on the same workstation where I am doing my Xcode development. It’s actually on a different network and therefore I cannot get to Couchbase using “localhost” as the connection address. I have to use https plus the IP address. Would that make a difference?

I’m pretty sure the loading of the cert in the project bundle was correct because I do not receive any errors and I also see the new common name referenced in the warning when I run the app.

When looking at the Couchbase server console, I do see some logging each time I fire up the app, so there is some communication going between the app and the sync gateway. In my local app, I am quite sure the documents I added to the sync gateway are not being downloaded into the lite version.

I’m going to go through the steps to enable SSL on the sync gateway, but any other thoughts or pointers would be much appreciated. Perhaps there is something else I need to do in addition to setAnchorCerts. Maybe I should try to separate all the CBL stuff into a separate swift file, as you have done yourself.

Thanks,
David

regarding “..but I think it might have to do with the fact that my Couchbase server is not on the same workstation”.
I am confused - did you mean the Couchbase Server or Sync Gateway? I am assuming that you are are installing the SSL certs associated with your sync gateway on your iOS app - if not, that’s what you should do because the Sync Gateway is the one talking to the iOS App. The Couchbase Server does not come into the picture as far as the iOS app goes (at least not directly). It talks to the Sync Gateway - hope that makes sense. So make sure setAnchorCerts is setting the cert of the Sync Gateway.

Clarification: I have two networks at home, one for business (with a static IP) and one for personal usage. I have both the Couchbase database and the Couchbase sync server on the business network and I’m doing development on the home network using Xcode 8 and Swift 3.

Up until adding SSL to the sync gateway, I have successfully been able to run my app (either on my home network or out in the wild) and capture and transfer data up to the Couchbase server via the sync gateway.

I started working on the reverse, where I update documents through the sync server and I want those updated documents to come down to the app which has Couchbase Lite installed. I updated the documents using the public REST API function, but I needed to install SSL for that to work.

Yes, I am installing and running the certs on the gateway, using the instructions per your developer documentation. In case it matters, both Couchbase and the sync gateway are on the same physical server.

I hope that makes a little sense.

Thanks,
David

OK. Thanks for clarifying. So since your sync gateway is hosted on a static IPAddress , please enter that for your common name when generating the cert. Now pin that cert into your app as discussed earlier.

Hi Priya, yes, that worked! I’ve been able to add/modify documents in the Public REST API and can see where the change shows up in the app.

However, for me to see the local sync’d data I have to write a small routine to cycle through all docs and print the contents to the debug window. Is there something where I can look directly into the local database to see all the documents? Something like the Query Workbench that can connect to a local copy of what is in Couchbase?

Thanks again,
David

Glad you have things working now. We don’t have an officially supported query workbench for CBL. Since you are on CBM 1.4 iOS , you can use this (not officially supported ) Mac application
https://github.com/couchbaselabs/CouchbaseLiteViewer.

You could also use http://sqlitebrowser.org to look into the sqlite content

1 Like