2012-02-05 27 views
5

Me gustaría exponer una API REST en mi aplicación, utilizando el servidor web Mongoose y proporcionando controladores para diferentes consultas.Parse REST consulta en C++

Un ejemplo de consulta sería así (sólo estoy usando GET, por el momento, el resto de los verbos HTTP vendrá después):

GET /items -> returns a list of all items in JSON 
GET /item/by/handle/123456789 -> returns item that has handle 123456789 
GET /item/by/name/My%20Item -> returns item(s) that have the name "My Item" 

Lo que estoy curioso es cómo debería poner en práctica el análisis de estas consultas. Puedo analizar fácilmente el primero, ya que es simplemente una cuestión de if(query.getURI() == "/items") return ....
Pero para las próximas dos consultas, tengo que manipular las cadenas std:: de una manera completamente diferente, usando magia y desfases std::string::find() para llegar al argumento.

A modo de ejemplo, esta es la aplicación que tengo para la segunda consulta:

size_t position = std::string::npos; 
std::string path = "/item/by/handle/"; 

if((position = query.getURI().find(path)) != std::string::npos) 
{ 
    std::string argument = query.getURI().substr(position + path.size()); 
    // now parse the argument to an integer, find the item and return it 
} 

¿Qué pasa si quiero "crear plantillas" esto; significado: describo la ruta y los argumentos que espero después (un entero, una cadena, ....); y el código se genera automáticamente para manejar esto?

Tl; Dr: Quiero ser capaz de manejar las consultas de descanso en C++ con algo en este sentido:

registerHandler("/item/by/handle/[INTEGER]", myHandlerMethod(int)); 

es esto posible?

+0

Parece que necesita expresiones regulares, como se encuentra en boost o C++ 11. –

Respuesta

4

Un enfoque bastante poco sexy, pero simple sería simplemente usar sscanf. Perdonen el código en lugar de C. Tenga en cuenta que esto no proporciona el tipo de sintaxis que está buscando, pero no requiere bibliotecas, extensiones ni impulso.

Por ejemplo,

 
int param; 
int a, b; 
char c[255]; 

/* recall that sscanf returns the number of variables filled */ 
if(1 == sscanf(query.getURI(), "/item/by/handle/%d", &param)) { 

    handler(param); 

} else if (3 == sscanf(query.getURI(), "/more/params/%d/%d/%s", &a, &b, &c)) { 

    anotherHandler(a, b, c); 

} else { 
    // 404 
} 
+2

Tenga en cuenta que el uso de% s es peligroso para la entrada del usuario, ya que no verifica los límites y puede sobrevolarse fácilmente. Sugiero para el ejemplo anterior: 'sscanf (query.getURI(),"/more/params /% d /% d /% 254s ", & a, & b, c)' – valenok

+0

Buen punto. Para aquellos que quieren evitar esto, Kernighan y Pike tienen una solución fácil: http://stackoverflow.com/questions/1621394/how-to-prevent-scanf-causing-a-buffer-overflow-in-c – Tom

1

mientras se alimentan a través de algún código Python, me encontré con que el marco Flask web tiene un particular way of parsing REST paths:

se declara una ruta como esta:

@app.route('/post/<int:post_id>') 
def show_post(post_id): 
    # show the post with the given id, the id is an integer 
    return 'Post %d' % post_id 

Y Flask crea lo que se necesita para darte el número entero que necesitas.

Eso es exactamente lo que necesito, así que supongo que tendré que hacerlo solo en C++.
Recibiré la respuesta de Tom, ya que es relevante, y creo que mi implementación se verá un poco como sugiere (aunque tiendo a preferir iostremas).

Dejaré esta respuesta aquí a cualquiera que esté al acecho.

+0

http: //expressjs.com/ también tiene una característica similar, también. – Tom

+0

¿Terminaste implementando esta sintaxis en C++? - Si es así, ¿ha considerado el open-sourcing? :) – stackoverflowuser95

+0

Ay, no.Terminé cambiando mi trabajo y encontré algunos otros problemas que abordar. – Gui13