JSON es una forma útil de transmitir datos. Ahora, N1QL puede consultarlo gracias a una actualización de CURL en Couchbase 5.0. Mira cómo conectarte a varios endpoints para hacerlo.
N1QL tiene muchas funciones que te permiten realizar una operación específica. Una de estas funciones que se ha añadido en el nuevo Couchbase 5.0 DP es CURL.
CURL le permite utilizar N1QL para interactuar con puntos finales JSON externos; es decir, API Rest que devuelven resultados y datos en formato JSON. Esta función permitirá a N1QL tener un conjunto conservador de funcionalidad curl incorporado en el lenguaje. La interacción consiste principalmente en la transferencia de datos hacia y desde un servidor utilizando los protocolos http y https. En resumen, la función CURL en N1QL le proporciona a usted, el usuario, un subconjunto de la funcionalidad estándar de curl (https://curl.haxx.se/docs/manpage.html) dentro de un lenguaje de consulta.
Para recuperar datos de diferentes servidores (como Google Maps, Yahoo Finanzas, etc.), podemos realizar peticiones GET o HTTP POST utilizando la función CURL. Esto se ve en el siguiente diagrama.
Definición de la función
CURL (URL, [opciones])
El primer argumento es la URL, que representa cualquier URL que apunte a un punto final JSON. Sólo se admiten URL con el protocolo http:// o https://. La redirección está desactivada.
Los argumentos de entrada de la función CURL() pueden ser tanto valores estáticos como expresiones N1QL evaluables.
Más adelante en el artículo veremos ejemplos que consultan desde la API de Google Geocode, la API de Yahoo Finanzas, la búsqueda de texto completo de Couchbase y la API de Github. El segundo argumento es una lista de opciones. Se trata de un objeto JSON que contiene una lista de opciones de curl y sus valores correspondientes.
Soportamos una variedad de opciones que le permiten interactuar con cualquier punto final de manera efectiva. En general, se pueden clasificar en opciones relacionadas con la seguridad y opciones generales. Al final del artículo se incluye una tabla con las opciones soportadas.
Funciones y mejoras de seguridad para CURL
Con la incorporación de la función CURL, para evitar vulnerabilidades de seguridad y controlar y minimizar los riesgos asociados a ella, se han implementado múltiples medidas de seguridad.
Uso de certificados CA con la función CURL de N1QL
Los certificados utilizados por la función N1QL CURL deben almacenarse en cada nodo de consulta dentro del clúster en el directorio n1qlcerts. La ubicación donde este directorio debe ser creado por el usuario depende de la ubicación de la instalación couchbase. (Es específico del sistema operativo). A continuación se asume la ubicación de instalación por defecto y se muestra dónde se ha creado el directorio n1qlcerts.
Linux | /opt/couchbase/var/lib/couchbase/n1qlcerts |
Mac OSX | /Users/couchbase/Library/Application\ Support/Couchbase/var/lib/couchbase/n1qlcerts |
Windows | C:Archivos de ProgramaCouchbase\Servervar\lib\couchbase\n1qlcerts |
Para ubicaciones de instalación no predeterminadas, es necesario crear la ruta relativa - "../var/lib/couchbase/n1qlcerts directory" desde el directorio bin desde el que se ejecuta cbq-engine.
Este directorio debe crearse para cada nodo de consulta.
Una vez creado este directorio, añade aquí el certificado que CURL va a utilizar. Para usar este certificado, usamos la opción cacert y pasamos el nombre del certificado.
Por ejemplo, si n1qlcerts/usuario1.pem es el nombre del certificado, utilice la opción cacert -.
"cacert": "usuario1.pem"
Sólo son válidos los nombres, las rutas no son válidas y pasar una de ellas provocará un error. CURL() lanza un error en el caso de certificados inválidos y caducados.
NOTA: El directorio n1qlcerts y su contenido deben replicarse en cada nodo de consulta del clúster.
Cabeceras y agente de usuario personalizados
CURL() se ejecuta en el nodo de consulta dentro de un clúster. Esto permite a la función acceder a todos los puntos finales REST accesibles a través del servicio de consulta (ya que es ahí donde se ejecuta la función). Para evitar el acceso a dichos puntos finales inseguros, se añade una cabecera personalizada, que no puede ser modificada por el usuario, a todas las peticiones enviadas utilizando la función curl N1QL. Tiene el formato "X-N1QL-User-Agent: couchbase/n1ql/1.7.0-N1QL".
También se establece siempre un user-agent por defecto. Se puede restablecer con la opción -user-agent. El valor por defecto es "couchbase/n1ql/1.7.0-N1QL".
Ambos valores están diseñados para permitir que los puntos finales internos y externos comprueben la cabecera/agente-usuario y no permitan el acceso en su código y denieguen el acceso a la función. La única advertencia al usar esto, sin embargo, es que todavía no podemos proteger contra cualquier software que no compruebe esta cabecera y las versiones existentes de software instalado localmente (tanto Couchbase como software que no sea Couchbase). Para estos casos, se ha añadido la función de curl whitelist (ver más abajo).
Creación de una lista blanca para restringir el acceso a CURL.
Una lista blanca es un documento JSON que enumera los puntos finales REST permitidos y las URL a las que puede acceder la función CURL(). Las propias URL deben coincidir con un prefijo. El documento de la lista blanca se crea dentro del directorio n1qlcerts (para ver la ubicación, consulte más arriba) y se denomina curl_whitelist.json (este nombre es fijo y el usuario no puede cambiarlo). El archivo (curl_whitelist.json) debe ser creado por el administrador (o un usuario con acceso a la máquina donde está instalado couchbase).
Si la lista blanca no está configurada (..../n1qlcerts/curl_whitelist.json no existe) o si existe pero está vacía, la función CURL no se puede utilizar.
Cualquier lista blanca necesita tener los siguientes campos -
Campo | Tipo | Descripción | Valor por defecto |
todo_acceso | booleano | Esto decidirá si el usuario tiene acceso a todas las urls o sólo a las urls especificadas en el array allowed_urls. | falso |
rizos_permitidos | matriz | Lista de prefijos para urls que deseamos permitir. | vacío |
urls_no_permitidas | matriz | Lista de prefijos para urls que estarán restringidas pase lo que pase | vacío |
Si el campo all_access es false, entonces el uso de la función CURL ha sido completamente restringido. Para poder usar CURL() con cualquier endpoint en N1QL, el administrador necesita establecer allowed_urls y disallowed_urls en consecuencia. Para permitir el acceso a todas las urls, podemos establecer all_access a true. Esto esencialmente nos da acceso completo a CURL.
Digamos, por ejemplo, que deseamos permitir el acceso a todos los endpoints de la api de google maps pero restringir el acceso a todos los demás endpoints. Lo siguiente será el contenido de la lista blanca.
Curl_whitelist.json
1 2 3 4 |
{ "all_access":falso, "urls_permitidas":["https://maps.googleapis.com"] } |
Cualquier url en CURL() prefijada por https://maps.googleapis.com/ se permitirá.
NOTA: La lista blanca debe replicarse en cada nodo de consulta del clúster.
Acceso basado en roles a la función CURL
Algo importante que vale la pena mencionar aquí es que CURL está diseñado para que no pueda ser invocado arbitrariamente. Para evitar la inyección de datos desde una fuente externa mediante la sentencia UPDATE, se ha añadido un nuevo rol QUERY_EXTERNAL_ACCESS. Sólo un usuario que tenga asignado este rol tiene acceso a la función CURL. Por defecto, este rol está vacío. Sólo puede acceder a la función CURL un FULL_ADMIN o cualquier usuario al que el FULL_ADMIN haya asignado el rol QUERY_EXTERNAL_ACCESS. Para versiones anteriores de couchbase que no soportan el control de acceso basado en roles, se puede utilizar un bucket protegido por contraseña. También para la funcionalidad CURL(), internamente se soporta un conjunto específico de cifrados SSL (MEDIUM o HIGH). Esto depende de COUCHBASE_SSL_CIPHER_LIST.
Restricción del tamaño de los resultados de CURL()
Un problema importante al utilizar la función CURL() es cuando un usuario crea un archivo realmente largo, de más de 64 MB, e intenta leerlo. Dado que los datos se cargan en memoria, si no se limita el tamaño del resultado, el servicio de consulta podría bloquearse. Debido a esta posibilidad, el tamaño máximo del resultado para los datos que puede devolver CURL() es de 64 MB (67 108 864 bytes). El usuario puede restringir la cantidad de memoria para los resultados CURL utilizando el parámetro resultado-cap El valor mínimo (por defecto) de la opción result-cap es 20MB ( 20 971 520 bytes).
Por ejemplo, si la consulta fija el límite de resultado en 20 MB - "result-cap":20971520, cualquier respuesta que tenga un tamaño superior devolverá un error.
Interacción con diferentes puntos finales
Veamos como consultar diferentes endpoints usando la función CURL en N1QL.
API de geocodificación de Google Maps
La API de geocodificación de Google Maps permite convertir direcciones estáticas en coordenadas y viceversa mediante una solicitud HTTP. (Para más información, consulte https://developers.google.com/maps/documentation/geocoding/intro )
Supongamos que quieres buscar Santa Cruz en España utilizando tu clave API de Google Dev. Para ello, puede utilizar la siguiente consulta:
Solicitud de rizos
1 |
rizo https://maps.googleapis.com/maps/api/geocode/json?address=santa+cruz&components=país:ES&key= |
Consulta correspondiente
1 |
SELECCIONE CURL("https://maps.googleapis.com/maps/api/geocode/json", {"get":verdadero,"datos":"address=santa+cruz&components=país:ES&key="}) GEO; |
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
"resultados": [ { "GEO": { "resultados": [ { "dirección_componentes": [ { "nombre_largo": "Santa Cruz de Tenerife", "nombre_corto": "Santa Cruz de Tenerife", "tipos": [ "localidad", "político" ] }, { "nombre_largo": "Santa Cruz de Tenerife", "nombre_corto": "TF", "tipos": [ "zona_administrativa_nivel_2", "político" ] }, { "nombre_largo": "Islas Canarias", "nombre_corto": "CN", "tipos": [ "zona_administrativa_nivel_1", "político" ] }, { "nombre_largo": "España, "nombre_corto": "ES", "tipos": [ "país", "político" ] } ], "dirección_formateada": "Santa Cruz de Tenerife, España", "geometría": { "límites": { "noreste": { "lat": 28.487616, "lng": -16.2356646 }, "suroeste": { "lat": 28.4280248, "lng": -16.3370045 } }, "localización": { "lat": 28.4636296, "lng": -16.2518467 }, "tipo_ubicación": "APROXIMADO", "viewport": { "noreste": { "lat": 28.487616, "lng": -16.2356646 }, "suroeste": { "lat": 28.4280248, "lng": -16.3370045 } } }, "place_id": "ChIJcUElzOzMQQwRLuV30nMUEUM", "tipos": [ "localidad", "político" ] } ], "status": "OK" } } ] |
Esta consulta recupera la dirección y los límites de localización geográfica de la dirección, Santa Cruz, ES. Utilizamos la dirección, los componentes y los parámetros clave de la API REST de geocodificación de Google Maps. La opción "data" representa la opción data de curl que representa datos HTTP POST. Sin embargo, dado que se trata de una solicitud get, establecemos la opción "get" en true. Puedes proporcionar valores a todos los parámetros REST dentro de la opción "data".
Ahora busquemos Half Moon Bay
1 |
SELECCIONE CURL("https://maps.googleapis.com/maps/api/geocode/json", {"datos":"dirección=Media+Luna+Bahía", "get":verdadero}) GEO; |
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
"resultados": [ { "GEO": { "resultados": [ { "dirección_componentes": [ { "nombre_largo": "Half Moon Bay", "nombre_corto": "Half Moon Bay", "tipos": [ "localidad", "político" ] }, { "nombre_largo": "Condado de San Mateo", "nombre_corto": "Condado de San Mateo", "tipos": [ "zona_administrativa_nivel_2", "político" ] }, { "nombre_largo": "California", "nombre_corto": "CA", "tipos": [ "zona_administrativa_nivel_1", "político" ] }, { "nombre_largo": "Estados Unidos", "nombre_corto": "US", "tipos": [ "país", "político" ] } ], "dirección_formateada": "Half Moon Bay, CA, EE.UU.", "geometría": { "límites": { "noreste": { "lat": 37.5226389, "lng": -122.4165183 }, "suroeste": { "lat": 37.4249286, "lng": -122.4778879 } }, "localización": { "lat": 37.4635519, "lng": -122.4285862 }, "tipo_ubicación": "APROXIMADO", "viewport": { "noreste": { "lat": 37.5226389, "lng": -122.4165183 }, "suroeste": { "lat": 37.4249286, "lng": -122.4778879 } } }, "place_id": "ChIJC8sZCqULj4ARVJvnNcic_V4", "tipos": [ "localidad", "político" ] } ], "status": "OK" } } ] |
API de Yahoo Finanzas
La API de Yahoo Finanzas le permite utilizar el Lenguaje de consulta de Yahoo (YQL) para obtener cotizaciones bursátiles (como se ve en http://meumobi.github.io/stocks%20apis/2016/03/13/get-realtime-stock-quotes-yahoo-finance-api.html ). A continuación se muestra la sentencia YQL SELECT para acceder a las acciones de Hortonworks Inc (HDP).
1 |
seleccionar * de yahoo.finanzas.citas donde símbolo en ("HDP") |
Para obtener los resultados en JSON puede utilizar la siguiente URL:
Solicitud de rizos
1 |
rizo https://query.yahooapis.com/v1/public/yql --data 'q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20(%22HDP%22)&format=json&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=' |
Consulta correspondiente
1 2 3 |
SELECCIONE temp.consulta.resultados de CURL("https://query.yahooapis.com/v1/public/yql", {"datos":"q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20(%22HDP%22)&format=json&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback="})temp; |
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
"resultados": [ { "resultados": { "presupuesto": { "AfterHoursChangeRealtime": null, "Ganancia anualizada": null, "Pregunta": "16.950", "AskRealtime": null, "Volumen medio diario: "952135", "Oferta": "16.940", "BidRealtime": null, "ValorLibro": "-0.654", "Cambiar": "+0.075", "Cambio de la media móvil de 50 días: "0.377", "CambioDePromedioMóvilDosDías": "3.625", "CambioDesdeAñoAlto": "-0.755", "ChangeFromYearLow": "10.525", "ChangePercentRealtime": null, "ChangeRealtime": null, "Cambio_Porcentual": "+0.075 - +0.445%", "CambioenPorcentaje": "+0.445%", "Comisión": null, "Divisa": "USD", "DíasAltos": "17.010", "DaysLow": "16.780", "DaysRange": "16.780 - 17.010", "DaysRangeRealtime": null, "CambioValorDías": null, "DaysValueChangeRealtime": null, "DividendPayDate": null, "Reparto de dividendos": null, "DividendYield": null, "EBITDA": "-223.00M", "EPSEstimateCurrentYear": "-1.720", "EPSEstimateNextQuarter": "-0.380", "EPSEstimateNextYear": "-1.190", "EarningsShare": "-3.737", "ErrorIndicationreturnedforsymbolchangedinvalid" (Indicación de error devuelta por símbolo cambiado no válido): null, "ExDividendDate": null, "FiftydayMovingAverage": "16.568", "LímiteAlto": null, "HoldingsGain": null, "HoldingsGainPercent": null, "HoldingsGainPercentRealtime": null, "HoldingsGainRealtime": null, "HoldingsValue": null, "HoldingsValueRealtime": null, "LastTradeDate": "10/5/2017", "LastTradePriceOnly": "16.945", "LastTradeRealtimeWithTime": null, "LastTradeTime": "12:50pm", "LastTradeWithTime": "12:50 - <b>16.945<\/b>", "LowLimit": null, "MarketCapRealtime": null, "Capitalización de mercado": "700.96M", "MoreInfo": null, "Nombre": "Hortonworks, Inc.", "Notas": null, "OneyrTargetPrice": "18.930", "Abierto": "17.010", "OrderBookRealtime": null, "PEGRatio": "-0.400", "PERatio": null, "PERatioRealtime": null, "CambioPercebtDesdeAñoAlto": "-4.266%", "CambioPorcentual": "+0.445%", "CambioPorcentualDeLaMediaMovil deCincuentaDías": "+2.275%", "CambioPorcentualDePromedioMóvilDosDías": "+27.214%", "PorcentajeCambioDesdeMínimoAño": "+163.941%", "CierreAnterior": "16.870", "Libro de precios": null, "PrecioEPSEstimadoAñoActual": null, "PrecioEPSEstimadoPróximoAño": null, "PrecioPagado": null, "PrecioVenta": "3.212", "AccionesPoseídas": null, "ShortRatio": "3.640", "Bolsa": "NMS", "Símbolo": "HDP", "TickerTrend": null, "TradeDate": null, "DosDíasDeMovimientoPromedio": "13.320", "Volumen": "217430", "AñoAlto": "17.700", "YearLow": "6.420", "AñoRango": "6.420 - 17.700", "símbolo": "HDP" } } } ] |
Para esta consulta, el valor de la opción data contiene los parámetros REST de Yahoo, q (para la consulta YQL), format (para devolver los datos en JSON) y algunos otros parámetros.
Búsqueda de texto completo en Couchbase
La búsqueda de texto completo de Couchbase permite aplicar búsquedas difusas a los datos almacenados en Couchbase. Para más información https://www.couchbase.com/blog/couchbase-4.5-developer-preview-couchbase-fts/.
Supongamos que creas un índice FTS llamado beers en el bucket beer-sample en Couchbase. Ahora puedes buscar cerveza tipo pale ale utilizando este índice, usando la función CURL en N1QL. Es importante tener en cuenta que FTS actualmente acepta HTTP POST en lugar de GET. Para especificar explícitamente el método de petición POST, utilice la opción request.
Solicitud de rizos
1 |
rizo -u cerveza-muestra:pase -XPOST -H "Content-Type: application/json" http://127.0.0.1:8094/api/index/beers/query -d '{ "explain": true, "fields": ["*"], "highlight": {}, "query": {"query": "pale ale"}}' |
Consulta correspondiente
1 2 3 4 5 |
SELECCIONE resultado.visitas_totales, longitud_array(resultado.hits) visitas_por_pagina DESDE CURL("http://localhost:8094/api/index/beers/query", {"solicitud":"POST","cabecera":"Content-Type: application/json", "datos":'{"explain":false, "fields": ["*"], "highlight": {}, "query": {"query": "pale ale"}}', "usuario":"Administrador:contraseña"}) resultado; |
1 2 3 4 5 6 |
"resultados": [ { "hits_per_page": 10, "total_hits": 3815 } ] |
Damos múltiples opciones en esta consulta. La opción header permite pasar una cabecera personalizada al servidor. Content-Type : application/json indica al servidor que los datos se proporcionan en formato JSON. Si tenemos un bucket protegido por contraseña en Couchbase, entonces necesitamos pasar sus credenciales con la consulta. La opción user se puede utilizar para pasar un nombre de usuario y una contraseña separados por dos puntos. La opción request especifica que se utiliza el método POST.
Si desea recuperar sólo los documentos de muestra-cerveza que devuelve la búsqueda anterior, puede escribir una consulta N1QL JOIN de la siguiente manera.
1 2 3 4 5 6 7 8 9 |
SELECCIONE ARRAY x.id para x en b1.resultado.hits FIN como hits, b1.resultado.visitas_totales como total, longitud_array(b1.resultado.hits), b DESDE (SELECCIONE CURL("http://localhost:8094/api/index/beers/query", {"solicitud":"POST","cabecera":"Content-Type: application/json", "datos":'{"explain":false, "fields": ["*"], "highlight": {}, "query": {"query": "pale ale"}}', "usuario":"Administrador:contraseña"}) resultado) b1 INTERIOR ÚNASE A `cerveza-muestra` b EN TECLAS b1.resultado.hits[*].id LÍMITE 1; |
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 |
"resultados": [ { "$1": 10, "b": { "abv": 5.4, "cervecería_id": "stone_brewing_co", "categoría": "Cerveza norteamericana", "descripción": "Nuestra cerveza insignia, la Stone Pale Ale, es nuestra interpretación californiana del clásico estilo pale ale británico. De color ámbar intenso, la Stone Pale Ale es robusta y de sabor pleno. Un delicado aroma a lúpulo se complementa con una rica maltosidad. Es una cerveza para los que han aprendido a apreciar el sabor distintivo. La Stone Pale Ale es estupenda sola o con comida que requiera una cerveza con carácter"., "ibu": 0, "nombre": "Stone Pale Ale", "srm": 0, "estilo": "American-Style Pale Ale", "tipo": "cerveza", "upc": 0, "actualizado": "2010-07-22 20:00:20" }, "éxitos": [ "piedra_cervecera_co-piedra_pale_ale", "flying_dog_brewery-classic_pale_ale", "yards_brewing-yards_philadelphia_pale_ale", "bell_s_brewery_inc-pale_ale", "sierra_nevada_cervecera_co-sierra_nevada_pale_ale", "cooper_s_cave_ale_company-cooper_s_cave_pale_ale", "appalachian_brewing_company-hoppy_trails_india_pale_ale", "cooperstown_brewing_company-backyard_india_pale_ale", "mogollon_brewing_company-superstition_pale_ale", "troegs_brewing-troegs_pale_ale" ], "total": 3815 } ] |
Esto recuperará los ids de los documentos devueltos por la consulta FTS que busca pale ale, junto con el total de aciertos y todos los detalles del documento correspondiente en beer-sample.
API de Github
La API de Github es un poco diferente de las anteriores, ya que devuelve múltiples resultados en forma de una matriz JSON de valores de resultado. Consulte la documentación de la API de Github en https://developer.github.com/v3/ para más detalles sobre lo que se puede consultar.
Digamos que quieres averiguar todos los repositorios vinculados a una cuenta de Github. La siguiente consulta lo hace
Solicitud de rizos
1 |
rizo -H "User-Agent: ikandaswamy" https://api.github.com/users/ikandaswamy/repos |
Consulta correspondiente
1 |
SELECCIONE RAW lista DESDE CURL("https://api.github.com/users/ikandaswamy/repos")lista LÍMITE 1; |
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
"resultados": [ { "archive_url": "https://api.github.com/repos/ikandaswamy/ds-algo/{archive_format}{/ref}", "assignees_url": "https://api.github.com/repos/ikandaswamy/ds-algo/assignees{/user}", "blobs_url": "https://api.github.com/repos/ikandaswamy/ds-algo/git/blobs{/sha}", "branches_url": "https://api.github.com/repos/ikandaswamy/ds-algo/branches{/branch}", "clone_url": "https://github.com/ikandaswamy/ds-algo.git", "colaboradores_url": "https://api.github.com/repos/ikandaswamy/ds-algo/collaborators{/colaborador}", "comments_url": "https://api.github.com/repos/ikandaswamy/ds-algo/comments{/number}", "commits_url": "https://api.github.com/repos/ikandaswamy/ds-algo/commits{/sha}", "compare_url": "https://api.github.com/repos/ikandaswamy/ds-algo/compare/{base}...{cabeza}", "content_url": "https://api.github.com/repos/ikandaswamy/ds-algo/contents/{+ruta}", "contributors_url": "https://api.github.com/repos/ikandaswamy/ds-algo/contributors", "fecha_creada": "2017-09-07T22:42:03Z", "rama_por_defecto": "maestro", "deployments_url": "https://api.github.com/repos/ikandaswamy/ds-algo/deployments", "descripción": "Úsalo para implementar varios problemas divertidos mientras reaprendes Estructuras de Datos y Algoritmos", "descargas_url": "https://api.github.com/repos/ikandaswamy/ds-algo/downloads", "events_url": "https://api.github.com/repos/ikandaswamy/ds-algo/events", "tenedor": falso, "horquillas": 0, "cuenta_horquillas": 0, "forks_url": "https://api.github.com/repos/ikandaswamy/ds-algo/forks", "nombre_completo": "ikandaswamy/ds-algo", "git_commits_url": "https://api.github.com/repos/ikandaswamy/ds-algo/git/commits{/sha}", "git_refs_url": "https://api.github.com/repos/ikandaswamy/ds-algo/git/refs{/sha}", "git_tags_url": "https://api.github.com/repos/ikandaswamy/ds-algo/git/tags{/sha}", "git_url": "git://github.com/ikandaswamy/ds-algo.git", "has_descargas": verdadero, "has_issues": verdadero, "has_pages": falso, "has_projects": verdadero, "has_wiki": verdadero, "página de inicio": null, "hooks_url": "https://api.github.com/repos/ikandaswamy/ds-algo/hooks", "html_url": "https://github.com/ikandaswamy/ds-algo", "id": 102792479, "issue_comment_url": "https://api.github.com/repos/ikandaswamy/ds-algo/issues/comments{/number}", "issue_events_url": "https://api.github.com/repos/ikandaswamy/ds-algo/issues/events{/number}", "issues_url": "https://api.github.com/repos/ikandaswamy/ds-algo/issues{/number}", "keys_url": "https://api.github.com/repos/ikandaswamy/ds-algo/keys{/key_id}", "labels_url": "https://api.github.com/repos/ikandaswamy/ds-algo/labels{/nombre}", "idioma": null, "idiomas_url": "https://api.github.com/repos/ikandaswamy/ds-algo/languages", "merges_url": "https://api.github.com/repos/ikandaswamy/ds-algo/merges", "hitos_url": "https://api.github.com/repos/ikandaswamy/ds-algo/milestones{/number}", "mirror_url": null, "nombre": "ds-algo", "notificaciones_url": "https://api.github.com/repos/ikandaswamy/ds-algo/notifications{?since,all,participating}", "temas_abiertos": 0, "recuento_temas_abiertos": 0, "propietario": { "avatar_url": "https://avatars1.githubusercontent.com/u/9203396?v=4", "events_url": "https://api.github.com/users/ikandaswamy/events{/privacy}", "followers_url": "https://api.github.com/users/ikandaswamy/followers", "following_url": "https://api.github.com/users/ikandaswamy/following{/otro_usuario}", "gists_url": "https://api.github.com/users/ikandaswamy/gists{/gist_id}", "gravatar_id": "", "html_url": "https://github.com/ikandaswamy", "id": 9203396, "login": "ikandaswamy", "organizaciones_url": "https://api.github.com/users/ikandaswamy/orgs", "received_events_url": "https://api.github.com/users/ikandaswamy/received_events", "repos_url": "https://api.github.com/users/ikandaswamy/repos", "site_admin": falso, "starred_url": "https://api.github.com/users/ikandaswamy/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/ikandaswamy/subscriptions", "tipo": "Usuario", "url": "https://api.github.com/users/ikandaswamy" }, "privado": falso, "pulls_url": "https://api.github.com/repos/ikandaswamy/ds-algo/pulls{/number}", "pushed_at": "2017-09-07T22:42:04Z", "releases_url": "https://api.github.com/repos/ikandaswamy/ds-algo/releases{/id}", "tamaño": 0, "ssh_url": "git@github.com:ikandaswamy/ds-algo.git", "stargazers_count": 0, "stargazers_url": "https://api.github.com/repos/ikandaswamy/ds-algo/stargazers", "status_url": "https://api.github.com/repos/ikandaswamy/ds-algo/statuses/{sha}", "suscriptores_url": "https://api.github.com/repos/ikandaswamy/ds-algo/subscribers", "subscription_url": "https://api.github.com/repos/ikandaswamy/ds-algo/subscription", "svn_url": "https://github.com/ikandaswamy/ds-algo", "tags_url": "https://api.github.com/repos/ikandaswamy/ds-algo/tags", "teams_url": "https://api.github.com/repos/ikandaswamy/ds-algo/teams", "trees_url": "https://api.github.com/repos/ikandaswamy/ds-algo/git/trees{/sha}", "updated_at": "2017-09-07T22:42:03Z", "url": "https://api.github.com/repos/ikandaswamy/ds-algo", "vigilantes": 0, "watchers_count": 0 } ] |
Si la cuenta tiene tres repositorios, la consulta devuelve tres resultados (aquí he añadido el límite 1). La palabra clave RAW se utiliza para devolver el array de documentos que devuelve la consulta, sin un objeto envoltorio. Un punto que notarás es que la opción de cabecera contiene el User-Agent con un nombre de usuario de github. Esto es ahora obligatorio para todas las peticiones a la API de Github.
Ahora, a partir de esta lista, digamos que le gustaría saber cuál es la url de clonación para cada uno de estos repos. La siguiente consulta logra esto
1 2 3 4 |
SELECCIONE clonar_url DESDE (SELECCIONE RAW lista DESDE CURL("https://api.github.com/users/ikandaswamy/repos", {"cabecera":"User-Agent: ikandaswamy"}) lista) s; |
1 2 3 4 5 6 7 8 9 10 11 |
"resultados": [ { "clone_url": "https://github.com/ikandaswamy/ds-algo.git" }, { "clone_url": "https://github.com/ikandaswamy/github-cheat-sheet.git" }, { "clone_url": "https://github.com/ikandaswamy/jsapp.git" } ] |
Resumen
Como puedes ver con los ejemplos anteriores, usando la función CURL, los usuarios de N1QL pueden ahora interactuar con cualquier API externa que devuelva resultados en formato JSON. Esto abre muchas posibilidades. Por ejemplo, si Couchbase contiene datos correspondientes a diferentes hoteles, entonces puedes utilizar la API de Google Maps para encontrar ubicaciones cercanas a cada uno de los hoteles correspondientes.
Para disponer de un entorno seguro con la incorporación de CURL() se han añadido múltiples mejoras de seguridad. La siguiente es una breve lista
- CURL se ejecuta en el nodo de consulta dentro de un clúster.
- La función CURL está desactivada por defecto.
- CURL sólo admite HTTP y HTTPS. Todos los demás protocolos están desactivados.
- No se permite la redirección de URL.
- El encabezado personalizado para N1QL CURL es "X-N1QL-User-Agent: couchbase/n1ql/1.7.0-N1QL".
- El User-Agent es "couchbase/n1ql/1.7.0-N1QL".
- Restringir la cantidad de memoria para los resultados CURL utilizando result-cap. El límite mínimo será de 20 MB y el máximo de 64 MB.
- El rol FULL_ADMIN permitirá el acceso a CURL. El rol QUERY_EXTERNAL_ACCESS puede ser asignado a un usuario por el FULL ADMIN. Esto permitirá al usuario utilizar la funcionalidad CURL.
- Los certificados deben almacenarse en la máquina local - cada nodo de consulta dentro de un cluster. Utilice ..../Couchbase/var/lib/couchbase/n1qlcerts para almacenar los certificados.Utilice cacert para pasar el "nombre" del certificado a utilizar. Sólo son válidos los nombres, las rutas no son válidas. (Pasar una ruta provocará un error).
- CURL lanza un error en caso de certificados inválidos/expirados.
- El usuario tiene la posibilidad de poner puntos finales en la "lista blanca".
La implementación N1QL de CURL utiliza la API golang libcurl - https://github.com/andelf/go-curl
Lista de opciones disponibles
Opciones de seguridad
Opción | Descripción | valor |
usuario | Usuario y contraseña del servidor
Cuando la contraseña está vacía se trata como una cadena de contraseña vacía. |
NOMBRE DE USUARIO[:CONTRASEÑA] |
básico | Utilizar autenticación básica HTTP | BOOLEANO (VERDADERO/FALSO) |
inseguro | Permitir conexiones a sitios SSL sin certificados (H) | BOOLEANO (VERDADERO/FALSO) |
anyauth | curl para averiguar el método de autenticación por sí mismo, y utilizar el más seguro | BOOLEANO (VERDADERO/FALSO) |
cacert | Especifique el nombre de archivo del certificado firmado por la CA
Los certificados deben almacenarse en la máquina local - cada nodo de consulta dentro de un cluster. /Couchbase/var/lib/couchbase/n1qlcerts para almacenar certificados. Esto no es visible para el usuario. El nombre de archivo no puede contener una ruta. Si no coincide con el contenido existente del directorio n1qlcerts, la función genera un error. Para los certificados caducados y no válidos lanzar un error. |
FILENAME (Este es el certificado, archivo pem para aws por ejemplo) |
resultado-cap | Establecer la capacidad del búfer que almacena el resultado de la operación CURL | Número de MB. (El mínimo son 20 MB) |
Otras opciones relacionadas con las transferencias
Opción | Descripción | Valor |
obtener, G | Obtener solicitud para CURL | BOOLEAN (verdadero/falso) |
X, solicitud | Establece el método de solicitud. Sólo acepta GET o POST y distingue entre mayúsculas y minúsculas.
En todos los demás casos, se produce un error. |
{"request": "POST"} |
tiempo de espera de conexión | Tiempo máximo de conexión. Debe contener el tiempo máximo en segundos que permite que dure la fase de conexión al servidor. Esto sólo limita la fase de conexión, no tiene ningún impacto una vez que se ha conectado. Póngalo a cero para cambiar al tiempo de espera de conexión incorporado por defecto - 300 segundos.
Si el valor es flotante, lo truncamos al valor entero. Para todos los demás tipos (que no sean un número) lanzar error. |
SEGUNDOS |
max-time | Tiempo máximo permitido para la operación de transferencia.
El tiempo de espera por defecto es 0 (cero), lo que significa que nunca se agota durante la transferencia. Si el valor es flotante, lo truncamos al valor entero. Para todos los demás tipos (que no sean un número) lanzar error. |
SEGUNDOS |
datos | Datos HTTP POST (H)
Nos permite establecer todos los parámetros rest api para el endpoint dado. |
CADENA
O [...cadena,cadena....] |
cabecera | Pasar cadena de encabezado personalizada al servidor (H) | CADENA
O [...cadena,cadena....] |
show-error | Mostrar error.
Si es verdadero, muestra los errores cuando se producen. Cuando es falso suprime los errores |
BOOLEANO (VERDADERO/FALSO) |
silencioso | Modo silencioso (no emite nada) | BOOLEANO (VERDADERO/FALSO) |
keepalive-time | Espera SEGUNDOS entre sondas keepalive para conectividad TCP de bajo nivel. (No afecta al nivel HTTP keep-alive) | SEGUNDOS |
agente de usuario | Valor para el User-Agent a enviar al servidor. | CADENA |
data-urlencode | Codificar los datos y enviarlos al servidor.
This is a test => this%20is%20a%20test |
CADENA
O [...cadena,cadena....] |