Esta semana, PouchDB v3.4.0 foi lançado com compatibilidade com o Couchbase Sync Gateway.
Nesta postagem, usaremos o exemplo TodoMVC existente e adicionaremos a sincronização filtrada usando a autenticação do Facebook. Além da sincronização entre clientes da Web, alteraremos ligeiramente o modelo de dados para sincronizar com os aplicativos ToDoLite existentes em execução no iOS e Android:
Para acompanhar o processo, você pode abrir e executar o exemplo do TodoMVC em commit d9bb961. Por conveniência, adicionei o código de login do Facebook em app.js. Quando o usuário faz o login, a função startSessionAndSync(accessToken, userId) é chamado. Agora vamos adicionar o código para que isso aconteça!
Início rápido
Certifique-se de servir o aplicativo na porta 9000 pois configuraremos o CORS para localhost:9000 mais tarde. O simples comando python deve servir:
1 |
$ python -m Servidor SimpleHTTPS 9000 |
Modelagem de dados
O TodoMVC e o ToDoLite têm um modelo de dados ligeiramente diferente. Nos aplicativos ToDoLite, um usuário pode criar várias listas e compartilhá-las com vários usuários.
Primeiro, vamos dar uma olhada em um documento de Tarefa com o esperado título e uma propriedade ID da lista fazendo referência à lista à qual pertence (nesse caso, 123):
1 2 3 4 5 6 |
{ "_id": "E9W3-9I2Y-O8W2-6Y4D", "tipo": "tarefa", "list_id": "123", "título": "Um título de tarefa" } |
Da mesma forma, um documento de lista também tem um título e um proprietário que faz referência ao usuário ao qual ele pertence:
1 2 3 4 5 6 |
{ "_id": "123", "tipo": "lista", "título": "Lista TodoMVC", "proprietário": "p:1234567890" } |
No entanto, o TodoMVC é um aplicativo de lista única. Para simplificar as coisas, podemos inserir o documento de lista no código assim que o usuário fizer login.
Vamos criar uma nova função chamada migrateGuestToUser para criar o documento de lista com o ID do usuário e salvá-lo no PouchDB:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
função migrateGuestToUser(userId) { var lista = { _id: '123', tipo: 'lista', título: 'Lista TodoMVC', proprietário: 'p:' + userId }; db.colocar(lista, função(erro, resultado) { se (!erro) { console.registro('Successfully saved user list' (Lista de usuários salva com sucesso)); } }) } |
Observação: É muito importante definir o campo proprietário, pois a função de sincronização rejeitará o documento caso contrário.
E podemos chamá-lo em startSessionAndSync:
1 2 3 |
função startSessionAndSync(accessToken, userId) { migrateGuestToUser(userId); } |
Os documentos de tarefa pertencem a uma lista e, portanto, têm um ID da lista que precisamos definir. Altere a propriedade addTodo função em app.js para que fique como abaixo. Observe que definimos o ID da lista para o campo hardcoded _id da lista que inserimos acima:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
função addTodo(texto) { var todo = { _id: novo Data().toISOString(), título: texto, verificado: falso, tipo: 'tarefa', ID da lista: '123', created_at: novo Data() }; db.colocar(todo, função retorno de chamada(erro, resultado) { se (!erro) { console.registro('Successfully posted a todo!); } }); } |
Agora que temos os documentos apropriados em conformidade com o modelo de dados do ToDoLite, podemos dar uma olhada na autenticação e na replicação.
Habilitação de CORS no Sync Gateway
Neste tutorial, executaremos uma instância local do Sync Gateway em localhost:4984 mas estamos servindo nosso aplicativo Web em localhost:9000. Nesse ponto, receberíamos um erro de política de mesma origem. Mas Chris recentemente adicionou o suporte a CORS ao Sync Gateway para essa finalidade. Portanto, não precisamos escrever uma única linha de código do lado do servidor :)
O CORS permite que os aplicativos da Web acessem recursos em outros domínios que não o domínio de origem. Ao ativar o CORS no Sync Gateway, estamos dizendo ao navegador "Sim, o nome de domínio do Sync Gateway tem permissão para se comunicar com este aplicativo Web". Abrir sync-gateway-config.json com a configuração extra do CORS para habilitá-lo em localhost:9000:
1 2 3 4 5 6 7 8 9 10 |
{ ... "CORS": { "Origem": ["http://localhost:9000"], "LoginOrigin": ["http://localhost:9000"], "Headers" (Cabeçalhos): ["Content-Type"], "MaxAge": 17280000 }, ... } |
Use o Sync Gateway 1.1 ou posterior. Inicie-o com o arquivo de configuração:
1 |
$ ~/Downloads/portais de sincronização sincronização-portal-configuração.json |
Voltar para app.jsatualize a url do remoteCouch de acordo:
1 2 |
var SYNC_GATEWAY_URL = 'http://127.0.0.1:4984/todos/'; var remoteCouch = SYNC_GATEWAY_URL; |
Agora, se tentarmos sincronizar a lista com o Sync Gateway, receberemos um erro 401 Unauthorized. Vamos corrigir isso criando uma sessão de usuário com o login do Facebook.
Autenticação com o Sync Gateway
Para autenticar com o Sync Gateway, podemos enviar uma solicitação POST para /todos/_facebook com o token de acesso, se recebermos um 200 OK, o navegador definirá o cookie de sessão retornado do Sync Gateway para futuras replicações push/pull.
1 2 3 4 5 6 7 8 9 10 11 12 |
função startSyncGatewaySession(accessToken) { var solicitação = novo XMLHttpRequest(); solicitação.aberto('POST', SYNC_GATEWAY_URL + '/_facebook', verdadeiro); solicitação.setRequestHeader('Content-Type', 'application/json'); solicitação.mudança de estado da leitura = função() { se (solicitação.estado de prontidão == 4 &lificador;&lificador; solicitação.status == 200) { console.registro(Nova sessão da SG, iniciando a sincronização!); sincronização(); }; solicitação.comCredenciais = verdadeiro; solicitação.enviar(JSON.stringify({"access_token": accessToken})); } |
Observação: É importante definir request.withCredentials = true em uma solicitação CORS para salvar o cookie retornado do Sync Gateway para futuras solicitações autenticadas (replicações push/pull).
Ligue para ele startSessionAndSync passando o accessToken voltamos do Facebook:
1 2 3 4 |
função startSessionAndSync(accessToken, userId) { migrateGuestToUser(userId); startSyncGatewaySession(accessToken); } |
Encerramento
Agora, abra o navegador e teste a sincronização dos itens de tarefas com outra janela do navegador aberta ou com os aplicativos nativos que executam o TodoLite.
Os usuários ainda podem criar tarefas sem estar conectados. Mas assim que um usuário faz login, as tarefas pertencem à lista do usuário. Fornecer um recurso de conta de convidado é um dos muitos benefícios da criação de recursos off-line primeiro.
Observe o Lista TodoMVC é exibido como uma tarefa no Chrome. Isso ocorre porque este exemplo estava usando o todos os documentos para exibir tarefas.
Na próxima postagem, usaremos as consultas Map/Reduce para adicionar o recurso de várias listas e um documento de perfil para compartilhá-las com outros usuários.
Leia mais:
- Configuração do CORS do Sync Gateway: https://www.couchbase.com/developers/mobile/#cors-configuration
- Ativação de cookies em uma solicitação CORS: http://www.html5rocks.com/en/tutorials/cors/#toc-withcredentials
- Replicações filtradas com o PouchDB: http://pouchdb.com/2015/04/05/filtered-replication.html
Olá James, obrigado pelo tutorial. Alguma ideia de como ativar o CORS no gateway de sincronização para máquinas Windows?
a compilação do commit e8cf146. Posso executar isso em uma máquina Windows?
Quando tento executar o sync_gateway com a configuração json, ele gera um erro:
XMLHttpRequest não pode ser carregado http://localhost:4984/todos/_facebook. Nenhum cabeçalho \'Access-Control-Allow-Origin\' está presente no recurso solicitado. Portanto, a origem \'http://localhost:9000\' não tem permissão de acesso.
Obrigado,
Nuthan.
Estou usando o Sync Gateway que construí a partir do mestre atual no Github. Ele deve incluir suporte a CORS e PouchDB?
Para mim, isso não acontece, os navegadores me informam \"Nenhum cabeçalho \'Access-Control-Allow-Origin\' está presente no recurso solicitado\".
Em meu arquivo config.json, adicionei as linhas CORS:
\"CORS\": {
\”Origin\”:[\”http://185.90.50.35:80\”],
\”LoginOrigin\”:[\”http://185.90.50.35:80\”],
\"Headers\":[\"Content-Type\"],
\"MaxAge\": 1728000
}
Você tem alguma ideia do motivo?)
O CORS não está funcionando para mim !!!! ainda não há \'Access-Control-Allow-Origin\'
Alguma solução?
Você está usando o Sync Gateway 1.1? Você também pode seguir este tutorial para configurar o CORS/PouchDB e as notificações Web Push https://github.com/couchbasela.... Informe-me se isso ainda não estiver funcionando para você.
No vídeo, você tem um navegador aberto com uma página da Web. Ela faz parte do Sync Gateway? Você precisa instalá-lo separadamente?
Tentei acessá-lo, mas só obtive erros 404.
Agradecimentos
Não importa. A interface de administração só aceita conexão de 127.0.0.1
Oi James
O CORS não está funcionando para mim.
ERRO:
XMLHttpRequest não pode carregar . A resposta à solicitação de preflight não passa na verificação de controle de acesso: O cabeçalho \'Access-Control-Allow-Origin\' contém o valor inválido \'\'. Portanto, o acesso à origem não é permitido.
Na sincronização, a solicitação tem o URL local como \'ORIGIN\' e o gateway como \'HOST\'. Mas o cabeçalho de resposta > \'Access-Control-Allow-Origin\'> é nulo e a solicitação está lançando um 204 No Content .
O Gateway de sincronização também foi configurado para ORIGEM específica / Todos os URLs, mas continua apresentando o mesmo problema.
Erros de CORS aqui também. Publiquei a seguinte pergunta no StackOverflow, caso alguém tenha tempo para dar uma olhada:
http://stackoverflow.com/quest…