Hace unos años, Brett Lawson hizo una gran serie de blogs sobre el uso de Couchbase Server y Node.js para el desarrollo de un framework de servidor de juegos. Desde entonces, el SDK de Node.js para Couchbase ha crecido significativamente de la versión 1.x a la 2.x.
En este artículo vamos a revisar esos tres posts originales y cambiarlos para que estén al día con los últimos estándares de Node.js y Express Framework, así como con la última versión del SDK de Node.js de Couchbase.
Requisitos previos
- Node.js 0.12
- Servidor Couchbase 4.0
Preparación del proyecto
Ya sea en Mac, Windows o Linux, la creación de una nueva aplicación Express Framework debe ser coherente entre ellos. Cree un nuevo directorio llamado gameapi-nodejs probablemente en su Escritorio y desde su Terminal (Mac / Linux) o Símbolo del sistema (Windows), ejecute el siguiente comando:
1 2 3 |
npm init |
Responda a las preguntas lo mejor que pueda. Por supuesto, el directorio del proyecto debe ser su directorio actual en el Símbolo del sistema o Terminal para que esto tenga éxito. Como alternativa al comando, puede crear y rellenar manualmente este archivo. Cree un nuevo archivo llamado package.json en el directorio de su proyecto y llénelo con lo siguiente:
1 2 3 4 5 6 7 8 9 |
{ "nombre": "gameapi-nodejs", "version": "1.0.0", "descripción": "Un ejemplo de uso del SDK de Node.js para Couchbase para crear un sencillo servidor de juegos", "autor": "Couchbase, Inc.", "licencia": "MIT" } |
No hemos terminado. Tenemos que instalar las dependencias del proyecto antes de que podamos empezar a planificar esta aplicación. Desde el símbolo del sistema o Terminal, ejecute el siguiente comando:
1 2 3 |
npm instale cuerpo-analizador couchbase express nodo-forja uuid --guardar |
Esto instalará Express Framework, el SDK de Couchbase Node.js, Forge para hash de contraseñas, UUID para generar valores únicos, y el middleware body-parser para manejar datos POST codificados en URL y JSON.
Preparación de la base de datos
Antes de empezar a codificar, Couchbase Server debe estar instalado con un bucket llamado juego-muestra creado.
Dado que este proyecto va a hacer uso de una de las principales características de Couchbase 4.0, necesitaremos configurar el bucket para crear un índice primario. Si estás usando una máquina Linux, Mac o Windows, esto se puede lograr fácilmente a través del cliente Couchbase Query (CBQ).
Mac
Para abrir CBQ en Mac, desde el Terminal, ejecute lo siguiente:
1 2 3 |
./Aplicaciones/Couchbase Servidor.aplicación/Contenido/Recursos/couchbase-núcleo/papelera/cbq |
Windows
Para abrir CBQ en Windows, desde el símbolo del sistema, ejecute lo siguiente:
1 2 3 |
C:/Programa Archivos/Couchbase/Servidor/papelera/cbq.exe |
Creación de un índice primario
Con CBQ abierto, ejecute lo siguiente:
1 2 3 |
CREAR PRIMARIO ÍNDICE EN `juegos-muestra` utilizando GSI; |
Tu cubo ya está listo para el resto del proyecto.
Estructura del proyecto
Nuestro proyecto va a constar de lo siguiente:
Artículo | Padres | Descripción |
---|---|---|
modelos | Todos los archivos de clase de la base de datos irán aquí | |
rutas | Todas las definiciones de los puntos finales de la API irán aquí | |
accountmodel.js | modelos | Crear y recuperar información sobre cuentas |
sessionmodel.js | modelos | Autenticación de usuarios y mantenimiento de la información de sesión |
statemodel.js | modelos | Crear, actualizar y recuperar información sobre el estado del juego |
rutas.js | rutas | Todos los endpoints para GET, POST, PUT estarán aquí |
app.js | Información sobre la configuración del servidor | |
config.json | Variables estáticas | |
paquete.json | Información sobre la dependencia |
Conceptos básicos
Antes de adentrarnos en la lógica del servidor de juegos Node.js, lo mejor es configurar la aplicación base Express Framework.
En la raíz del proyecto, cree y abra un archivo llamado config.json ya que contendrá información estática como la información de conectividad de Couchbase. Incluya lo siguiente cuando esté abierto:
1 2 3 4 5 6 7 8 |
{ "couchbase": { "servidor": "127.0.0.1:8091", "cubo": "juego-muestra" } } |
En la raíz del proyecto, cree y abra un archivo llamado app.js ya que contendrá toda la información básica sobre el funcionamiento del servidor Node.js. Incluye lo siguiente cuando hayas abierto el archivo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
var express = requiere("express"); var bodyParser = requiere("body-parser"); var couchbase = requiere("couchbase"); var config = requiere("./config"); var aplicación = express(); aplicación.utilice(bodyParser.json()); aplicación.utilice(bodyParser.urlencoded({ ampliado: verdadero })); // Declaración global del servidor Couchbase y del bucket a utilizar módulo.exportaciones.cubo = (nuevo couchbase.Grupo(config.couchbase.servidor)).openBucket(config.couchbase.cubo); // Todos los puntos finales que se utilizarán en esta aplicación var rutas = requiere("./routes/routes.js")(aplicación); var servidor = aplicación.escuche(3000, función () { consola.registro("Escuchando en el puerto %s...", servidor.dirección().puerto); }); |
Vamos a desglosar lo que vemos aquí. Las primeras líneas son nosotros incluyendo las dependencias en nuestra aplicación. No hay nada especial. Lo que es importante es lo siguiente:
1 2 3 4 |
aplicación.utilice(bodyParser.json()); aplicación.utilice(bodyParser.urlencoded({ ampliado: verdadero })); |
Esto significa que vamos a analizar datos JSON y datos codificados en URL de los cuerpos de las peticiones. En particular las peticiones POST y PUT. Lo siguiente que vamos a hacer es inicializar el cluster de Couchbase en la aplicación y abrir un único bucket para su uso dentro de la aplicación:
1 2 3 |
módulo.exportaciones.cubo = (nuevo couchbase.Grupo(config.couchbase.servidor)).openBucket(config.couchbase.cubo); |
Incluyendo module.exports.bucket estamos diciendo que vamos a usarlo a través de la aplicación. Ahora en otros archivos JavaScript, si queremos acceder al cubo podemos simplemente hacer:
1 2 3 |
var cubo = requiere("relative/path/to/app").cubo; |
A continuación verás que incluimos nuestro pronto creado rutas/routes.js y pasándole el archivo aplicación como uno de los argumentos. Lo que esto hace será obvio pronto.
Por último, llamando a app.listen le estamos diciendo a Node.js que escuche en el puerto 3000 para peticiones. La aplicación es casi utilizable en su estado más básico. Crear y abrir rutas/routes.js y añade las siguientes líneas:
1 2 3 4 5 6 7 8 9 10 11 |
var appRouter = función(aplicación) { aplicación.consiga("/", función(consulte, res) { res.estado(403).enviar("No es un punto final válido"); }); } módulo.exportaciones = appRouter; |
La aplicación se puede ejecutar ahora ejecutando node app.js desde el símbolo del sistema o el terminal. Aterrizar en http://localhost:3000 debería mostrar el mensaje "Not a valid endpoint".
El modelo de datos de la API
Antes de sumergirse en el código que importa, es mejor saber cómo se verán los datos en Couchbase. Para cualquier usuario, habrá cuatro documentos con el siguiente aspecto:
El documento del usuario
El documento de usuario contendrá toda la información sobre un usuario. Para esta aplicación esa información será un nombre, un nombre de usuario y una contraseña.
El nombre de este documento llevará el prefijo usuario:: y se le añade un valor uid único. Esta estrategia de nomenclatura de documentos utiliza lo que se denomina claves compuestas.
1 2 3 4 5 6 7 8 9 |
{ "tipo": "usuario", "uid", "", "nombre": "", "nombre de usuario": "", "contraseña": "" } |
El documento del nombre de usuario
El documento de nombre de usuario contendrá sólo el valor uid que se encuentra en el documento de usuario. El propósito del documento de nombre de usuario puede ser pensado como un documento de método de inicio de sesión. Por ejemplo, podría representar un simple inicio de sesión en el que el usuario introduce un nombre de usuario y una contraseña. Dado que el documento contiene el uid de enlace, puede vincularse al documento de usuario. El documento de nombre de usuario lleva el prefijo nombre de usuario:: y se le añade el nombre de usuario real. Se puede utilizar una estrategia similar si se utilizan Facebook o Twitter como métodos de inicio de sesión y vincularlos también a través del campo uid.
1 2 3 4 5 6 |
{ "tipo": "nombre de usuario", "uid": "" } |
El documento de sesión
El documento de sesión es un documento de caducidad automática que actúa como ruta del usuario hacia información más segura. En teoría, el front-end del usuario almacenará el valor sid y lo pasará entre endpoints protegidos. Con él, se puede acceder a un uid vinculado a un usuario.
1 2 3 4 5 6 7 |
{ "tipo": "sesión", "sid": "", "uid": "" } |
El Documento de Estado
El documento de estado contendrá información sobre el estado particular del juego. Por ejemplo, si al personaje le quedan cinco vidas y veinte pociones, esa información se guardará aquí. Hay información de versión para evitar conflictos entre dos sesiones de juego activas que se guardan bajo la misma cuenta.
1 2 3 4 5 6 7 8 9 10 11 12 |
{ "tipo": "estado", "uid": "", "estados": { "nombre-estado": { "version": 1, "datos": { } } } } |
Creación del modelo de cuenta
El modelo de cuenta servirá para tres fines concretos:
- Crear una cuenta de usuario
- Recuperación de una cuenta de usuario
- Comparar una contraseña con hash con una contraseña sin hash
Antes de empezar a codificar, necesitamos poner nuestros includes en orden. Añade lo siguiente a la parte superior del archivo models/accountmodel.js file:
1 2 3 4 5 6 |
var uuid = requiere("uuid"); var forja = requiere("node-forge"); var db = requiere("../app").cubo; var N1qlQuery = requiere(couchbase).N1qlQuery; |
Basándonos en el modelo de datos visto anteriormente, para crear una cuenta de usuario se necesitará un nombre, un nombre de usuario y una contraseña. Con esa información en la mano, la contraseña será hash, y la información del usuario se almacenará junto a un documento de referencia como este:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
AccountModel.crear = función(parámetros, devolución de llamada) { var userDoc = { tipo: "usuario", uid: uuid.v4(), nombre: parámetros.nombre, nombre de usuario: parámetros.nombre de usuario, contraseña: forja.md.sha1.crear().actualización(parámetros.contraseña).resumen().toHex() }; var referenceDoc = { tipo: "nombre de usuario", uid: userDoc.uid }; db.insertar("nombre de usuario::" + userDoc.nombre de usuario, referenceDoc, función(error) { si(error) { devolución de llamada(error, null); devolver; } db.insertar("usuario::" + userDoc.uid, userDoc, función(error, resultado) { si(error) { devolución de llamada(error, null); devolver; } devolución de llamada(null, {mensaje: "éxito", datos: resultado}); }); }); }; |
Observe que en el código anterior, primero intentamos insertar un nuevo documento de referencia. Si falla (puede que ya exista), no se guardará ningún documento y en su lugar se devolverá el mensaje de error. Tanto si es un éxito como un fracaso, la llamada de retorno del archivo de rutas se ejecuta para mostrar cualquier tipo de respuesta al solicitante.
En términos de lectura de datos de usuario, una de dos cosas podría suceder. Podríamos pasar un nombre de usuario porque estamos haciendo un simple login of-sorts, o podríamos pasar un id de usuario. Depende de lo que estamos después. Digamos que sólo estamos iniciando sesión con el nombre de usuario, es probable que desee llamar a una función como esta:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
AccountModel.getByUsername = función(parámetros, devolución de llamada) { var consulta = N1qlQuery.fromString( "select users.* from `gaming-sample` as usernames" + "join `gaming-sample` as users on keys ("usuario::" || usernames.uid) " + "where meta(nombresdeusuario).id = $1" ); db.consulta(consulta, ["nombre de usuario::" + parámetros.nombre de usuario], función(error, resultado) { si(error) { devolver devolución de llamada(error, null); } devolución de llamada(null, resultado); }); }; |
Fíjate en que estamos usando una consulta N1QL, nueva en Couchbase 4.0. Es muy similar al SQL tradicional y además nos da la comodidad de no tener que crujir o formatear datos en la capa de aplicación. Couchbase Server hará todo esto por nosotros. No obstante, tenemos la opción de solicitar datos como en versiones anteriores de Couchbase y otras plataformas NoSQL.
En la sentencia N1QL anterior, estamos seleccionando un documento con la clave compuesta anexada a nuestro nombre de usuario en texto plano. Se produce una unión con la propiedad uid del documento usernames (clave externa) y el documento users (clave primaria).
Esto nos lleva a la validación de una contraseña. Aquí no se hace ninguna llamada a la base de datos. Simplemente vamos a tomar una contraseña en bruto, hash, a continuación, comparar el hash con la contraseña almacenada.
1 2 3 4 5 |
AccountModel.validatePassword = función(rawPassword, hashedPassword) { devolver forja.md.sha1.crear().actualización(rawPassword).resumen().toHex() === hashedPassword ? verdadero : falso; }; |
Para hacer models/accountmodel.js utilizable en nuestro archivo de rutas debemos exportarlo así en la parte inferior del
models/accountmodel.js código:
1 2 3 |
módulo.exportaciones = AccountModel; |
Creación del modelo de sesión
El modelo de sesión servirá para tres fines concretos:
- Crear una sesión de usuario
- Recuperación de una sesión de usuario
- Validación de una sesión de usuario
Antes de empezar a codificar, necesitamos poner nuestros includes en orden. Añade lo siguiente a la parte superior del archivo modelos/sessionmodel.js file:
1 2 3 4 |
var uuid = requiere("uuid"); var db = requiere("../app").cubo; |
Crear una sesión
Cuando un usuario desea crear una sesión, debe proporcionar un uid. Con esto en la mano, se crea un id de sesión único y se inserta en la base de datos con una caducidad. Cuando expire, se eliminará automáticamente de Couchbase sin intervención del usuario, cerrando así su sesión.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
SessionModel.crear = función(uid, devolución de llamada) { var sessionDoc = { tipo: "sesión", sid: uuid.v4(), uid: uid }; db.insertar("sesión::" + sessionDoc.sid, sessionDoc, {"caducidad": 3600}, función(error, resultado) { si(error) { devolución de llamada(error, null); devolver; } devolución de llamada(null, sessionDoc.sid); }); }; |
Autenticación de un usuario
Una vez creada la sesión de usuario, el identificador de sesión debe utilizarse cada vez que el usuario desee acceder a un punto final protegido.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
SessionModel.autentifique = función(consulte, res, siguiente) { si(!consulte.cabeceras.autorización) { siguiente("Debe estar autorizado para su uso"); } var authInfo = consulte.cabeceras.autorización.dividir(" "); si(authInfo[0] === "Portador") { var sid = authInfo[1]; SessionModel.consiga(sid, función(error, resultado) { si(error) { devolver siguiente(error); } SessionModel.actualizar(sid, función() {}); consulte.uid = resultado.valor.uid; siguiente(); }); } }; |
En el código anterior, la función recibirá un identificador de sesión que utilizará para comprobar si ya existe una sesión. En caso afirmativo, restablecerá el tiempo de expiración de la sesión y devolverá el uid asociado a la misma. La obtención de la información de la sesión puede verse de la siguiente manera:
1 2 3 4 5 6 7 8 9 10 11 |
SessionModel.consiga = función(sid, devolución de llamada) { db.consiga("sesión::" + sid, función(error, resultado) { si(error) { devolución de llamada(error, null); devolver; } devolución de llamada(null, resultado); }); }; |
No está mal, ¿verdad? Finalmente puedes ver que el reinicio de sesión ocurre de manera similar:
1 2 3 4 5 6 7 8 9 |
SessionModel.actualizar = función(sid, devolución de llamada) { db.toque("sesión::" + sid, 3600, función(error, resultado) { si(error) { devolución de llamada(error, null); } }); }; |
El método táctil no añadirá tiempo, sino que lo restablecerá. En este caso, reiniciará el temporizador a una hora.
Para hacer modelos/sessionmodel.js utilizable en nuestro archivo de rutas debemos exportarlo así en la parte inferior del modelos/sessionmodel.js código:
1 2 3 |
módulo.exportaciones = SessionModel; |
Creación del modelo de Estado
El modelo estatal servirá para dos fines concretos:
- Crear o actualizar un estado guardado
- Recuperar un estado guardado por nombre
Antes de empezar a codificar, necesitamos poner nuestros includes en orden. Añade lo siguiente a la parte superior del archivo models/statemodel.js file:
1 2 3 4 5 6 |
var uuid = requiere("uuid"); var couchbase = requiere("couchbase"); var N1qlQuery = requiere(couchbase).N1qlQuery; var db = requiere("../app").cubo; |
Creación de un estado de guardado
El objetivo de crear o actualizar un save-state es que primero comprobemos si existe. Si no existe, lo crearemos. Si existe, entonces obtendremos cualquier información que exista, la cambiaremos, y luego reemplazaremos lo que exista actualmente en la base de datos. Todo esto se hace mientras se incrementa la versión del estado para evitar conflictos entre los guardados del juego. No realmente para evitar conflictos al guardar en Couchbase, sólo para asegurarnos de que no coges el juego en dos dispositivos y anulas los datos del juego con un guardado mucho más antiguo.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
StateModel.guardar = función(uid, nombre, preVer, datos, devolución de llamada) { db.consiga("usuario::" + uid + "::state", función(error, resultado) { si(error && error.código !== couchbase.errores.keyNotFound) { devolución de llamada(error, null); devolver; } var stateDoc = { tipo: "estado", uid: uid, estados: {} }; si(resultado != null && resultado.valor) { stateDoc = resultado.valor; } var stateBlock = { versión: 0, datos: null }; si(stateDoc.estados[nombre]) { stateBlock = stateDoc.estados[nombre]; } si no { stateDoc.estados[nombre] = stateBlock; } si(stateBlock.versión !== preVer) { devolver devolución de llamada({"status": "error", "mensaje": "Su versión no coincide con la versión del servidor"}); } si no { stateBlock.versión++; stateBlock.datos = datos; } var stateOptions = {}; si(resultado != null && resultado.valor) { stateOptions.cas = resultado.cas; } db.upsert("usuario::" + uid + "::state", stateDoc, stateOptions, función(error, resultado) { si(error) { devolver devolución de llamada(error, null); } devolución de llamada(null, stateBlock); }); }); }; |
Véase el upsert allí. En Couchbase eso significa crear si no existe, o reemplazar si existe. Muy conveniente para cosas como guardar estados para un juego.
Conseguir los Estados
Esto nos deja con la obtención de cualquier save-state que hayamos creado.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
StateModel.getByUserIdAndName = función(uid, nombre, devolución de llamada) { db.consiga("usuario::" + uid + "::state", función(error, resultado) { si(error) { si(error.código !== couchbase.errores.keyNotFound) { devolver devolución de llamada(null, {}); } si no { devolver devolución de llamada(error, null); } } si(!resultado.valor.estados[nombre]) { devolver devolución de llamada({"status": "error", "mensaje": "El Estado no existe"}, null); } devolución de llamada(null, resultado.valor.estados[nombre]); }); }; |
El concepto detrás de esto es que estamos haciendo una búsqueda de documentos basada en un ID de usuario. Si el documento de estado para un uid en particular existe, entonces haz una búsqueda en el array asociativo para ver si el nombre del estado existe. Si existe, devuelve cualquier contenido de estado que exista para el nombre.
Para hacer models/statemodel.js utilizable en nuestro archivo de rutas debemos exportarlo así en la parte inferior del models/statemodel.js código:
1 2 3 |
módulo.exportaciones = StateModel; |
Creación de las rutas API
Ya hemos creado todos los modelos de datos necesarios, así que es hora de encadenarlos con rutas accesibles para el usuario. Volviendo al modelo rutas/routes.js empezaremos por añadir las rutas del modelo de cuenta:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
aplicación.Correo electrónico:("/api/usuario", función(consulte, res) { si(!consulte.cuerpo.nombre) { devolver res.estado(400).enviar({"status": "error", "mensaje": "Se requiere un nombre"}); } si no si(!consulte.cuerpo.nombre de usuario) { devolver res.estado(400).enviar({"status": "error", "mensaje": "Se requiere un nombre de usuario"}); } si no si(!consulte.cuerpo.contraseña) { devolver res.estado(400).enviar({"status": "error", "mensaje": "Se requiere una contraseña"}); } AccountModel.crear(consulte.cuerpo, función(error, resultado) { si(error) { devolver res.estado(400).enviar(error); } res.enviar(resultado); }); }); |
El endpoint anterior espera una petición POST con un parámetro de cuerpo nombre, nombre de usuario y contraseña Estamos a la escucha de POST porque es la mejor práctica utilizar POST al crear o insertar datos a través de una petición HTTP. Si existen los tres, entonces el endpoint AccountModel.create() y, finalmente, devuelve un error o un resultado en función del éxito del método. Si al menos uno de los parámetros requeridos no existe, se devuelve un error. Se puede ver una lista de códigos de error aquí.
Un endpoint para obtener información del usuario no es tan importante en este ejemplo, así que saltaremos directamente a autenticar al usuario y crear una sesión. En el rutas/routes.js añada lo siguiente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
aplicación.consiga("/api/auth", función(consulte, res, siguiente) { si(!consulte.consulta.nombre de usuario) { devolver siguiente(JSON.stringify({"status": "error", "mensaje": "Debe proporcionarse un nombre de usuario"})); } si(!consulte.consulta.contraseña) { devolver siguiente(JSON.stringify({"status": "error", "mensaje": "Debe proporcionarse una contraseña"})); } AccountModel.getByUsername(consulte.consulta, función(error, usuario) { si(error) { devolver res.estado(400).enviar(error); } si(!AccountModel.validatePassword(consulte.consulta.contraseña, usuario[0].contraseña)) { devolver res.enviar({"status": "error", "mensaje": "La contraseña introducida no es válida"}); } SessionModel.crear(usuario[0].uid, función(error, resultado) { si(error) { devolver res.estado(400).enviar(error); } res.setHeader("Autorización", "Portador" + resultado); res.enviar(usuario); }); }); }); |
El punto final de autenticación espera un nombre de usuario y una contraseña. Si se encuentran ambos, se buscará el usuario. Si se encuentra el usuario, se realiza una comparación de la contraseña y, si tiene éxito, se creará una sesión.
Los dos últimos puntos finales de la API que nos son útiles son para obtener y crear estados guardados. Comenzando con la creación de un endpoint de estado guardado, en su rutas/routes.jsañade lo siguiente:
1 2 3 4 5 6 7 8 9 10 |
aplicación.poner("/api/state/:nombre", SessionModel.autentifique, función(consulte, res, siguiente) { StateModel.guardar(consulte.uid, consulte.parámetros.nombre, parseInt(consulte.consulta.preVer, 10), consulte.cuerpo, función(error, resultado) { si(error) { devolver res.enviar(error); } res.enviar(resultado); }); }); |
El punto final anterior espera un parámetro de URL que represente el nombre del estado, un parámetro de consulta que represente la versión actual del estado y un cuerpo de solicitud que puede contener cualquier JSON imaginable, ya que representa los datos del juego que merece la pena guardar.
Por último, nos queda obtener los estados que se han guardado.
1 2 3 4 5 6 7 8 9 10 |
aplicación.consiga("/api/state/:nombre", SessionModel.autentifique, función(consulte, res, siguiente) { StateModel.getByUserIdAndName(consulte.uid, consulte.parámetros.nombre, función(error, resultado) { si(error) { devolver res.enviar(error); } res.enviar(resultado); }); }); |
El punto final anterior espera un parámetro URL que represente el estado de guardado concreto que se desea encontrar. Por supuesto, también espera que el usuario se autentique primero.
Probar la API
Los puntos finales de la API que creamos en el módulo rutas/routes.js se puede probar de varias maneras. Dos de mis formas favoritas de probarlo son con la extensión Postman para Chrome o con cURL. Pruébalo tú mismo usando cURL:
1 2 3 4 5 6 7 8 9 10 11 12 |
rizo -X POST http://localhost:3000/api/user --data "name=Nic%20Raboy&username=nraboy&password=12345" RESPUESTA: { "mensaje": "éxito", "datos": { "cas": "16588775686144" } } |
Arriba seguimos adelante y creamos una nueva cuenta de usuario
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
rizo -X GET "http://localhost:3000/api/auth?username=nraboy&password=12345" RESPUESTA: [ { "nombre": "Nic Raboy", "contraseña": "8cb2237d0679ca88db6464eac60da96345513964", "tipo": "usuario", "uid":"c3e834b0-867e-4a43-aede-b15a4e139adc", "nombre de usuario": "nraboy" } ] |
Arriba creamos una sesión de usuario. Esta misma estrategia se puede aplicar para los otros puntos finales también.
Conclusión
Usando Node.js y el SDK de Couchbase Server, puedes crear fácilmente una API backend para tus juegos. En Couchbase 4.0 ahora tienes la libertad de usar N1QL como opción para consultar datos en tu aplicación.
La aplicación Node.js completa sobre la que se ha escrito en este artículo puede descargarse gratuitamente de la dirección Couchbase Labs GitHub repositorio.
Hola,
¿Sigue siendo necesario habilitar N1QL en couchbase 4 ejecutando \'bucket.enableN1ql(\'localshot:8093\');\'? Gracias
nope, sólo funciona con el último SDK
quiero preguntarle por el error de un cliente:\"
[com.couchbase.client.deps.io.netty.util.ResourceLeakDetector] FALLO: ByteBuf.release() no fue llamado antes de ser recolectado. Habilite el informe avanzado de fugas para averiguar dónde se produjo la fuga. Para habilitar el informe avanzado de fugas, especifique la opción JVM \'-Dcom.couchbase.client.deps.io.netty.leakDetectionLevel=advanced\' o llame a ResourceLeakDetector.setLevel()\".
¿Cuál es el problema?
Hola,
¿Se puede usar N1QL sólo para consultas o se puede usar para hacer los UPSERT\'s e INSERT\'s? Gracias
En este momento INSERT, UPDATE, DELETE, UPSERT son beta. Puedes usarlos, pero hasta que no salgan de la beta no recomendamos usarlos en un entorno de producción.
http://developer.couchbase.com…
Lo mejor,