Skip to content

Commit

Permalink
mime-type check, returning 406 on invalid type
Browse files Browse the repository at this point in the history
-Stricter mime-type checking

Resolves: https://jira.duraspace.org/browse/FCREPO-1840
  • Loading branch information
bseeger committed Jan 28, 2016
1 parent 6bd534d commit 797a4aa
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 14 deletions.
48 changes: 37 additions & 11 deletions fcrepo-http-api/src/main/java/org/fcrepo/http/api/FedoraLdp.java
Expand Up @@ -18,27 +18,25 @@

import static com.hp.hpl.jena.rdf.model.ResourceFactory.createResource;
import static javax.ws.rs.core.MediaType.APPLICATION_XHTML_XML;
import static javax.ws.rs.core.MediaType.APPLICATION_XML;
import static javax.ws.rs.core.MediaType.TEXT_HTML;
import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
import static javax.ws.rs.core.Response.Status.NOT_IMPLEMENTED;
import static javax.ws.rs.core.Response.created;
import static javax.ws.rs.core.Response.notAcceptable;
import static javax.ws.rs.core.Response.noContent;
import static javax.ws.rs.core.Response.ok;
import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
import static javax.ws.rs.core.Response.Status.NOT_IMPLEMENTED;
import static javax.ws.rs.core.Response.Status.CONFLICT;
import static javax.ws.rs.core.Response.Status.UNSUPPORTED_MEDIA_TYPE;
import static javax.ws.rs.core.Response.Status.FORBIDDEN;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.http.HttpStatus.SC_BAD_REQUEST;
import static org.apache.jena.riot.WebContent.contentTypeSPARQLUpdate;
import static org.fcrepo.http.commons.domain.RDFMediaType.JSON_LD;
import static org.fcrepo.http.commons.domain.RDFMediaType.N3;
import static org.fcrepo.http.commons.domain.RDFMediaType.N3_ALT2;
import static org.fcrepo.http.commons.domain.RDFMediaType.NTRIPLES;
import static org.fcrepo.http.commons.domain.RDFMediaType.RDF_XML;
import static org.fcrepo.http.commons.domain.RDFMediaType.TURTLE;
import static org.fcrepo.http.commons.domain.RDFMediaType.TURTLE_X;
import static org.fcrepo.kernel.api.FedoraTypes.FEDORA_BINARY;
import static org.fcrepo.kernel.api.FedoraTypes.FEDORA_CONTAINER;
import static org.fcrepo.kernel.api.FedoraTypes.FEDORA_PAIRTREE;
Expand All @@ -53,6 +51,7 @@
import java.net.URLDecoder;
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;

import javax.annotation.PostConstruct;
Expand Down Expand Up @@ -81,9 +80,11 @@
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilderException;
import javax.ws.rs.core.Variant;

import org.fcrepo.http.commons.domain.ContentLocation;
import org.fcrepo.http.commons.domain.PATCH;
import org.fcrepo.http.commons.domain.RDFMediaType;
import org.fcrepo.kernel.api.exception.InvalidChecksumException;
import org.fcrepo.kernel.api.exception.MalformedRdfException;
import org.fcrepo.kernel.api.exception.RepositoryRuntimeException;
Expand All @@ -102,7 +103,7 @@
import com.codahale.metrics.annotation.Timed;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Splitter;

import com.google.common.collect.ImmutableList;
import static com.google.common.base.Strings.nullToEmpty;

/**
Expand Down Expand Up @@ -177,6 +178,7 @@ public Response head() {

/**
* Outputs information about the supported HTTP methods, etc.
*
* @return the outputs information about the supported HTTP methods, etc.
*/
@OPTIONS
Expand All @@ -192,21 +194,45 @@ public Response options() {
* Retrieve the node profile
*
* @param rangeValue the range value
* @return triples for the specified node
* @return the binary or the triples for the specified node
* @throws IOException if IO exception occurred
*/
@GET
@Produces({TURTLE + ";qs=10", JSON_LD + ";qs=8",
N3, N3_ALT2, RDF_XML, NTRIPLES, APPLICATION_XML, TEXT_PLAIN, TURTLE_X,
TEXT_HTML, APPLICATION_XHTML_XML})
@Produces({TURTLE + ";qs=10", "*/*"})
public Response describe(@HeaderParam("Range") final String rangeValue) throws IOException {
checkCacheControlHeaders(request, servletResponse, resource(), session);

LOGGER.info("GET resource '{}'", externalPath);

final ImmutableList<MediaType> acceptableMediaTypes =
new ImmutableList.Builder<MediaType>().addAll(headers.getAcceptableMediaTypes()).build();

if (acceptableMediaTypes.size() > 0) {

final List<Variant> possibleVariants = new ArrayList();
if (resource() instanceof FedoraBinary) {
final String lang = null;
final String enc = null;
possibleVariants.add(new Variant(MediaType.valueOf(((FedoraBinary) resource()).getMimeType()),
lang, enc));
} else {
possibleVariants.addAll(RDFMediaType.POSSIBLE_RDF_VARIANTS);
}

final boolean match = acceptableMediaTypes.stream().anyMatch(x ->
x.isWildcardType() || possibleVariants.stream().anyMatch(t -> t.getMediaType().isCompatible(x)));

if (!match) {
LOGGER.info("Unable to produce content in the requested mime-type(s): " );
acceptableMediaTypes.stream().forEach(x -> LOGGER.info(x.toString()));

return notAcceptable(possibleVariants).build();
}
}
addResourceHttpHeaders(resource());

final RdfStream rdfStream = new RdfStream().session(session)
.topic(translator().reverse().convert(resource()).asNode());
.topic(translator().reverse().convert(resource()).asNode());

return getContent(rangeValue, getChildrenLimit(), rdfStream);

Expand Down
Expand Up @@ -64,7 +64,7 @@ public void testGetDatastreamNode() throws IOException {
final HttpGet method =
new HttpGet(serverAddress + pid + "/ds1");

method.addHeader("Accept", "text/html");
method.addHeader("Accept", "text/plain");
assertEquals(200, getStatus(method));
}

Expand Down
Expand Up @@ -67,10 +67,11 @@ public abstract class RDFMediaType extends MediaType {

public static final List<Variant> POSSIBLE_RDF_VARIANTS = mediaTypes(
RDF_XML_TYPE, TURTLE_TYPE, N3_TYPE, N3_ALT2_TYPE, NTRIPLES_TYPE, APPLICATION_XML_TYPE,
TEXT_PLAIN_TYPE, TURTLE_X_TYPE, JSON_LD_TYPE).add().build();
TEXT_PLAIN_TYPE, TURTLE_X_TYPE, JSON_LD_TYPE, TEXT_HTML_TYPE, APPLICATION_XHTML_XML_TYPE).add().build();

public static final String POSSIBLE_RDF_RESPONSE_VARIANTS_STRING[] = {
TURTLE, N3, N3_ALT2, RDF_XML, NTRIPLES, TEXT_PLAIN, APPLICATION_XML, TURTLE_X, JSON_LD };
TURTLE, N3, N3_ALT2, RDF_XML, NTRIPLES, TEXT_PLAIN, APPLICATION_XML, TURTLE_X, JSON_LD, TEXT_HTML,
APPLICATION_XHTML_XML};

private static MediaType typeFromString(final String type) {
return new MediaType(type.split("/")[0], type.split("/")[1]);
Expand Down

0 comments on commit 797a4aa

Please sign in to comment.