From 6ed2f0117d8b94d62cd2c65a1a2e115a398c3dcf Mon Sep 17 00:00:00 2001 From: Tpt Date: Wed, 15 Jul 2020 22:47:16 +0200 Subject: [PATCH] Adds basic SPARQL UPDATE support to the server --- server/src/main.rs | 110 +++++++++++++++++++++++++++++++++++- server/templates/query.html | 28 +++++---- 2 files changed, 121 insertions(+), 17 deletions(-) diff --git a/server/src/main.rs b/server/src/main.rs index 21b4a180..1197c098 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -22,7 +22,9 @@ use http_types::{ }; use oxigraph::io::{DatasetFormat, GraphFormat}; use oxigraph::model::{GraphName, NamedNode}; -use oxigraph::sparql::{Query, QueryOptions, QueryResults, QueryResultsFormat, ServiceHandler}; +use oxigraph::sparql::{ + Query, QueryOptions, QueryResults, QueryResultsFormat, ServiceHandler, Update, +}; use oxigraph::RocksDbStore; use std::fmt; use std::io::{BufReader, Cursor}; @@ -135,7 +137,37 @@ async fn handle_request(request: Request, store: RocksDbStore) -> Result { + if let Some(content_type) = request.content_type() { + if content_type.essence() == "application/sparql-update" { + let mut buffer = String::new(); + let mut request = request; + request + .take_body() + .take(MAX_SPARQL_BODY_SIZE) + .read_to_string(&mut buffer) + .await?; + evaluate_sparql_update(store, buffer, Vec::new(), Vec::new()).await? + } else if content_type.essence() == "application/x-www-form-urlencoded" { + let mut buffer = Vec::new(); + let mut request = request; + request + .take_body() + .take(MAX_SPARQL_BODY_SIZE) + .read_to_end(&mut buffer) + .await?; + evaluate_urlencoded_sparql_update(store, buffer).await? + } else { + simple_response( + StatusCode::UnsupportedMediaType, + format!("Not supported Content-Type given: {}", content_type), ) } } else { @@ -252,6 +284,60 @@ async fn evaluate_sparql_query( .await } +async fn evaluate_urlencoded_sparql_update( + store: RocksDbStore, + encoded: Vec, +) -> Result { + let mut update = None; + let mut default_graph_uris = Vec::new(); + let mut named_graph_uris = Vec::new(); + for (k, v) in form_urlencoded::parse(&encoded) { + match k.as_ref() { + "update" => update = Some(v.into_owned()), + "using-graph-uri" => default_graph_uris.push(v.into_owned()), + "using-named-graph-uri" => named_graph_uris.push(v.into_owned()), + _ => { + return Ok(simple_response( + StatusCode::BadRequest, + format!("Unexpected parameter: {}", k), + )) + } + } + } + if let Some(update) = update { + evaluate_sparql_update(store, update, default_graph_uris, named_graph_uris).await + } else { + Ok(simple_response( + StatusCode::BadRequest, + "You should set the 'update' parameter", + )) + } +} + +async fn evaluate_sparql_update( + store: RocksDbStore, + update: String, + default_graph_uris: Vec, + named_graph_uris: Vec, +) -> Result { + if !default_graph_uris.is_empty() || !named_graph_uris.is_empty() { + return Ok(simple_response( + StatusCode::BadRequest, + "using-graph-uri and using-named-graph-uri parameters are not supported yet", + )); + } + spawn_blocking(move || { + let update = Update::parse(&update, None).map_err(|e| { + let mut e = Error::from(e); + e.set_status(StatusCode::BadRequest); + e + })?; + store.update(update)?; + Ok(Response::new(StatusCode::NoContent)) + }) + .await +} + async fn http_server< F: Clone + Send + Sync + 'static + Fn(Request) -> Fut, Fut: Send + Future>, @@ -522,6 +608,26 @@ mod tests { exec(request, StatusCode::Ok) } + #[test] + fn post_update() { + let mut request = + Request::new(Method::Post, Url::parse("http://localhost/update").unwrap()); + request.insert_header("Content-Type", "application/sparql-update"); + request.set_body( + "INSERT DATA { }", + ); + exec(request, StatusCode::NoContent) + } + + #[test] + fn post_bad_update() { + let mut request = + Request::new(Method::Post, Url::parse("http://localhost/update").unwrap()); + request.insert_header("Content-Type", "application/sparql-update"); + request.set_body("INSERT"); + exec(request, StatusCode::BadRequest) + } + fn exec(request: Request, expected_status: StatusCode) { let mut path = temp_dir(); path.push("temp-oxigraph-server-test"); diff --git a/server/templates/query.html b/server/templates/query.html index 04effa5d..bb74a92d 100644 --- a/server/templates/query.html +++ b/server/templates/query.html @@ -3,25 +3,23 @@ Oxigraph server - - + + -
-
- - +