couchbase-lite-net: CB Lite 2.0 – Replication Error 400 Bad Request

Hi,

for reference: I already posted about this issue in the couchbase forums: https://forums.couchbase.com/t/cb-lite-2-0-replication-error-400-bad-request/14207

Some Basic Info:

  • We are using Xamarin with .NET Standard Library (1.4).
  • We are mainly building for a UWP project, but I checked Android and get the same error there.
  • We are using CB-Lite 2.0 db016 // CB-Server 5.0.0 // Sync-Gateway 1.5
  • The Server and Sync-Gateway-Setup is from the Travel-Sample 2.0 iOS Demo (http://docs.couchbase.com/tutorials/travel-sample-mobile.html?lesson=01-overview)
  • The Setup works absolutely fine with the iOS-Swift-App and Python-Backend from the above documentation

The Problem: Well, the most obvious problem is that the sync is not working. When creating a new document via .NET, it is not pushed into the bucket. Also I put a document into the bucket via iOS-App/Python-Backend and it is not pulled (db.GetDocument returns null). When I break in “onReplicationCompleted” the “replicationEvent” also contains a LastError: LastError = {LiteCore.LiteCoreException: LiteCoreException (400): Bad Request}

Also the console in which the sync-gateway runs doesn’t even show a connection-request. When I connect via browser (http://our.couchbase.server.ip:4985/travel-sample/_all_docs?include_docs=true), iOS-Demo or Python-Backend it shows the existing document correctly and in the console of the running sync-gateway I see the connection-requests.

What I’ve tried:

  • Using “walrus:” with a different bucket instead of the existing bucket on the cb-server
  • With and without Channel (see code below)
  • With and without User (see code below)
  • Using PCL instead of .Net Standard
  • Usind Shared Project instead of .Net Standard

Code in the “MainPage.xaml.cs” of the .NET Standard Library:

    public MainPage()
    {
        

        this.db = new Database("sync-db");

        Uri url = new Uri("ws://our.cb.server.ip:4984/travel-sample");
        var config = new ReplicatorConfiguration(db, url);
        config.Continuous = true;
        config.ReplicatorType = ReplicatorType.PushAndPull;
        config.Authenticator = new BasicAuthenticator("demo", "password");
        config.Options.Channels = new List<String>();
        config.Options.Channels.Add("channel.demo");

        this.replication = new Replicator(config);
        this.replication.StatusChanged += this.onReplicationCompleted;
        this.replication.Start();
        
        InitializeComponent();
    }

    void onReplicationCompleted(object sender, ReplicationStatusChangedEventArgs replicationEvent)
    {
        if (replicationEvent.Status.Activity == ReplicatorActivityLevel.Stopped)
        {
            Console.WriteLine("Replication has completed.");
        }
    }

Sync Gateway Config: We are using the sync-config from the working iOS 2.0 sample: (source: https://github.com/couchbaselabs/mobile-travel-sample/blob/master/sync-gateway-config-travelsample.json)

{
      "interface":":4984",
      "adminInterface":":4985",
      "log": ["*"],
      "databases": {
        "travel-sample": {
          "import_docs": "continuous",
          "unsupported": {
            "enable_extended_attributes": true,
            "replicator_2":true
          },
          "bucket":"travel-sample",
          "server": "http://localhost:8091",
          "username": "***",
          "password": "***",
          "users":{
              "admin": {"password": "password", "admin_channels": ["*"]}, 
              "demo": {"password": "password"},
              "tester": {"password": "password"}
          },
        "sync": `
    function sync(doc, oldDoc) {

    /* Just ignore all the static travel-sample files */
      var type = getType();
      if (type == "landmark" || type == "hotel" || type == "airport" || type =="airline" || type == "route") {
             return;
      } 
      /* validation */
       var username = getUserName();
       // Verify the user making the request is the same as the one in doc's username
       requireUser(doc.username);

     
       if (!isDelete()) {
          // Validate required fields.
          validateNotEmpty("username", doc.username);


          if (isCreate()) {

            // Validate that the _id is prefixed by owner.
            var expectedDocId = "user" + "::" + doc.username;

            if (expectedDocId != doc._id) {
                throw({forbidden: "user doc Id must be of form user:userId"});
         
            }
          
          } else {
             // Validate that the username hasn't changed.
            validateReadOnly("username", doc.username, oldDoc.username);
          }

        }


      /* Routing */
      // Add doc to the user's channel.
      channel("channel." + username);

      
      // Give user read access to channel
       if (!isDelete()) {
        // Deletion of user document is essentially deletion of user
           access(username,"channel." + username)
       }


      function getType() {
        return (isDelete() ? oldDoc.type : doc.type);
      }

      function getUserName() {
        return (isDelete() ? oldDoc.username : doc.username);
      }

      function isCreate() {
        // Checking false for the Admin UI to work
        return ((oldDoc == false) || (oldDoc == null || oldDoc._deleted) && !isDelete());
      }

      function isUpdate() {
        return (!isCreate() && !isDelete());
      }

      function isDelete() {
        return (doc._deleted == true);
      }

      function validateNotEmpty(key, value) {
        if (!value) {
          throw({forbidden: key + " is not provided."});
        }
      }

      function validateReadOnly(name, value, oldValue) {
        if (value != oldValue) {
          throw({forbidden: name + " is read-only."});
        }
      }


      
    }
          `
        }
      }
    }

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 30 (12 by maintainers)

Commits related to this issue

Most upvoted comments

@bdgza Same server-setup and same console-program. Just uninstall Nuget, clean and install db014. I think db015 also works for the console program. But if I remember correctly, that version had some Issues with our Xamarin setup.