diff --git a/src/SipiHttpServer.cpp b/src/SipiHttpServer.cpp index cff7b192..2b632149 100644 --- a/src/SipiHttpServer.cpp +++ b/src/SipiHttpServer.cpp @@ -1191,6 +1191,7 @@ static void serve_iiif(Connection &conn_obj, const std::string &uri, std::vector params) { + auto headRequest = conn_obj.method() != Connection::HEAD; // // getting the identifier (which in case of a PDF or multipage TIFF my contain a page id (identifier@pagenum) // @@ -1387,7 +1388,7 @@ static void serve_iiif(Connection &conn_obj, } } try { - conn_obj.sendFile(infile); + if (headRequest) conn_obj.sendFile(infile); } catch (shttps::InputFailure iofail) { syslog(LOG_WARNING, "Browser unexpectedly closed connection"); } catch (Sipi::SipiError &err) { @@ -1430,7 +1431,7 @@ static void serve_iiif(Connection &conn_obj, try { //!> send the file from cache - conn_obj.sendFile(cachefile); + if (headRequest) conn_obj.sendFile(cachefile); //!> from now on the cache file can be deleted again } catch (shttps::InputFailure err) { // -1 was thrown @@ -1530,7 +1531,7 @@ static void serve_iiif(Connection &conn_obj, conn_obj.header("Content-Type", "image/jpeg");// set the header (mimetype) conn_obj.setChunkedTransfer(); Sipi::SipiCompressionParams qp = { { JPEG_QUALITY, std::to_string(server->jpeg_quality()) } }; - img.write("jpg", "HTTP", &qp); + if (headRequest) img.write("jpg", "HTTP", &qp); break; } case SipiQualityFormat::JP2: { @@ -1538,7 +1539,7 @@ static void serve_iiif(Connection &conn_obj, conn_obj.header("Link", canonical_header); conn_obj.header("Content-Type", "image/jp2");// set the header (mimetype) conn_obj.setChunkedTransfer(); - img.write("jpx", "HTTP"); + if (headRequest) img.write("jpx", "HTTP"); break; } case SipiQualityFormat::TIF: { @@ -1547,7 +1548,7 @@ static void serve_iiif(Connection &conn_obj, conn_obj.header("Content-Type", "image/tiff");// set the header (mimetype) // no chunked transfer needed... - img.write("tif", "HTTP"); + if (headRequest) img.write("tif", "HTTP"); break; } case SipiQualityFormat::PNG: { @@ -1556,7 +1557,7 @@ static void serve_iiif(Connection &conn_obj, conn_obj.header("Content-Type", "image/png");// set the header (mimetype) conn_obj.setChunkedTransfer(); - img.write("png", "HTTP"); + if (headRequest) img.write("png", "HTTP"); break; } default: { @@ -1701,6 +1702,7 @@ void SipiHttpServer::run() add_route(Connection::GET, "/favicon.ico", favicon_handler); add_route(Connection::GET, "/", iiif_handler); + add_route(Connection::HEAD, "/", iiif_handler); user_data(this); diff --git a/test/e2e/conftest.py b/test/e2e/conftest.py index bf99b361..d4cd41b6 100644 --- a/test/e2e/conftest.py +++ b/test/e2e/conftest.py @@ -298,7 +298,7 @@ def compare_server_images(self, url_path, expected_file_path, headers=None): raise SipiTestError( "Sipi compare: pixels not identical {} {}:\n {}".format(downloaded_file_path, expected_file_path, compare_process.stdout)) - def expect_status_code(self, url_path, status_code, headers=None): + def expect_status_code(self, url_path, status_code, headers=None, method='get'): """ Requests a file and expects to get a particular HTTP status code. @@ -308,15 +308,13 @@ def expect_status_code(self, url_path, status_code, headers=None): """ sipi_url = self.make_sipi_url(url_path) - response = requests.get(sipi_url, headers=headers) + response = getattr(requests, method)(sipi_url, headers=headers) if response.status_code != status_code: - raise SipiTestError( - "Received status code {} for URL {}, expected {} (wrote {}). Response:\n{}".format(response.status_code, - sipi_url, - status_code, - self.sipi_log_file, - response.text)) + format = "Received status code {} for URL {}, expected {} (wrote {}). Response:\n{}" + raise SipiTestError(format.format(response.status_code, sipi_url, status_code, self.sipi_log_file, response.text)) + + return response def get_image_info(self, url_path, headers=None): """ diff --git a/test/e2e/test_02_server.py b/test/e2e/test_02_server.py index 0d353aed..95387617 100644 --- a/test/e2e/test_02_server.py +++ b/test/e2e/test_02_server.py @@ -18,22 +18,21 @@ # See the GNU Affero General Public License for more details. # You should have received a copy of the GNU Affero General Public # License along with Sipi. If not, see . -import filecmp -import pprint -import shutil -import pytest from pathlib import Path +import datetime +import filecmp import os import os.path -import time -import datetime +import pprint +import pytest +import shutil +import subprocess import sys - +import time # Tests basic functionality of the Sipi server. - class TestServer: component = "The Sipi server" @@ -161,6 +160,15 @@ def test_odd_file(self, manager): downloaded_file_path = manager.download_file("/unit/{}/file".format(filename)) assert filecmp.cmp(manager.data_dir_path("knora/test_odd.odd"), downloaded_file_path) + def test_head_response_should_be_empty(self, manager): + response_json = manager.post_file("/api/upload", manager.data_dir_path("unit/lena512.tif"), "image/tiff") + + http_response = manager.expect_status_code("/unit/{}/full/max/0/default.jpg".format(response_json["filename"]), 200) + process = subprocess.run(['file', '-'], input=http_response.content, capture_output=True) + assert process.stdout.startswith(b'/dev/stdin: JPEG image data, JFIF standard 1.01, aspect ratio, density 1x1, segment length 16') + + http_response = manager.expect_status_code("/unit/{}/full/max/0/default.jpg".format(response_json["filename"]), 200, method='head') + assert http_response.text == "" def test_mimeconsistency(self, manager): """upload any file and check mimetype consistency"""