SPARQL HTTP graph store: do not normalizes URIs

Bug: #92
pull/96/head
Tpt 4 years ago
parent d43b3ac038
commit 477d1cb930
  1. 1
      server/Cargo.toml
  2. 72
      server/src/main.rs

@ -24,6 +24,7 @@ http-types = "2"
oxigraph = { version = "0.2", path="../lib", features = ["http_client"] } oxigraph = { version = "0.2", path="../lib", features = ["http_client"] }
rand = "0.8" rand = "0.8"
url = "2" url = "2"
oxiri = "0.1"
[dev-dependencies] [dev-dependencies]
tempfile = "3" tempfile = "3"

@ -28,10 +28,11 @@ use oxigraph::sparql::{Query, QueryResults, QueryResultsFormat, Update};
use oxigraph::RocksDbStore as Store; use oxigraph::RocksDbStore as Store;
#[cfg(all(feature = "sled", not(feature = "rocksdb")))] #[cfg(all(feature = "sled", not(feature = "rocksdb")))]
use oxigraph::SledStore as Store; use oxigraph::SledStore as Store;
use oxiri::Iri;
use rand::random; use rand::random;
use std::io::BufReader; use std::io::BufReader;
use std::str::FromStr; use std::str::FromStr;
use url::{form_urlencoded, Url}; use url::form_urlencoded;
const MAX_SPARQL_BODY_SIZE: u64 = 1_048_576; const MAX_SPARQL_BODY_SIZE: u64 = 1_048_576;
const HTML_ROOT_PAGE: &str = include_str!("../templates/query.html"); const HTML_ROOT_PAGE: &str = include_str!("../templates/query.html");
@ -292,11 +293,8 @@ async fn handle_request(request: Request, store: Store) -> Result<Response> {
.map_err(bad_request)?; .map_err(bad_request)?;
Response::new(StatusCode::NoContent) Response::new(StatusCode::NoContent)
} else if let Some(format) = GraphFormat::from_media_type(content_type.essence()) { } else if let Some(format) = GraphFormat::from_media_type(content_type.essence()) {
let graph = NamedNode::new( let graph =
base_url(&request)? resolve_with_base(&request, &format!("/store/{:x}", random::<u128>()))?;
.join(&format!("/store/{:x}", random::<u128>()))?
.into_string(),
)?;
store store
.load_graph( .load_graph(
BufReader::new(SyncAsyncReader::from(request)), BufReader::new(SyncAsyncReader::from(request)),
@ -344,14 +342,24 @@ async fn handle_request(request: Request, store: Store) -> Result<Response> {
}) })
} }
fn base_url(request: &Request) -> Result<Url> { fn base_url(request: &Request) -> Result<String> {
let mut url = request.url().clone(); let mut url = request.url().clone();
if let Some(host) = request.host() { if let Some(host) = request.host() {
url.set_host(Some(host)).map_err(bad_request)?; url.set_host(Some(host)).map_err(bad_request)?;
} }
url.set_query(None); url.set_query(None);
url.set_fragment(None); url.set_fragment(None);
Ok(url) Ok(url.into_string())
}
fn resolve_with_base(request: &Request, url: &str) -> Result<NamedNode> {
Ok(NamedNode::new_unchecked(
Iri::parse(base_url(request)?)
.map_err(bad_request)?
.resolve(url)
.map_err(bad_request)?
.into_inner(),
))
} }
fn url_query(request: &Request) -> Vec<u8> { fn url_query(request: &Request) -> Vec<u8> {
@ -525,16 +533,7 @@ fn store_target(request: &Request) -> Result<Option<GraphName>> {
"Both graph and default parameters should not be set at the same time", "Both graph and default parameters should not be set at the same time",
); );
} else { } else {
Some( Some(resolve_with_base(request, &graph)?.into())
NamedNode::new(
base_url(request)?
.join(&graph)
.map_err(bad_request)?
.into_string(),
)
.map_err(bad_request)?
.into(),
)
} }
} else if default { } else if default {
Some(GraphName::DefaultGraph) Some(GraphName::DefaultGraph)
@ -542,9 +541,7 @@ fn store_target(request: &Request) -> Result<Option<GraphName>> {
None None
}) })
} else { } else {
Ok(Some( Ok(Some(resolve_with_base(request, "")?.into()))
NamedNode::new(base_url(request)?.into_string())?.into(),
))
} }
} }
@ -697,6 +694,7 @@ mod tests {
use super::*; use super::*;
use crate::handle_request; use crate::handle_request;
use async_std::task::block_on; use async_std::task::block_on;
use http_types::Url;
use tempfile::{tempdir, TempDir}; use tempfile::{tempdir, TempDir};
#[test] #[test]
@ -848,6 +846,38 @@ mod tests {
ServerTest::new().test_status(request, StatusCode::BadRequest) ServerTest::new().test_status(request, StatusCode::BadRequest)
} }
#[test]
fn graph_store_url_normalization() {
let server = ServerTest::new();
// PUT
let mut request = Request::new(
Method::Put,
Url::parse("http://localhost/store?graph=http://example.com").unwrap(),
);
request.insert_header("Content-Type", "text/turtle");
request.set_body("<http://example.com> <http://example.com> <http://example.com> .");
server.test_status(request, StatusCode::Created);
// GET good URI
server.test_status(
Request::new(
Method::Get,
Url::parse("http://localhost/store?graph=http://example.com").unwrap(),
),
StatusCode::Ok,
);
// GET bad URI
server.test_status(
Request::new(
Method::Get,
Url::parse("http://localhost/store?graph=http://example.com/").unwrap(),
),
StatusCode::NotFound,
);
}
#[test] #[test]
fn graph_store_protocol() { fn graph_store_protocol() {
// Tests from https://www.w3.org/2009/sparql/docs/tests/data-sparql11/http-rdf-update/ // Tests from https://www.w3.org/2009/sparql/docs/tests/data-sparql11/http-rdf-update/

Loading…
Cancel
Save