Modifying allowed Mime Types for RESTCONF

Change-Id: Idf96164a23aeaf81dedb55b1de198b2a06f33c15
This commit is contained in:
Sean Condon 2018-05-21 17:53:22 +01:00 committed by Henry Yu
parent 74ce2c1009
commit e4042d3486
4 changed files with 111 additions and 20 deletions

View File

@ -0,0 +1,31 @@
/*
* Copyright 2018-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.restconf.api;
import javax.ws.rs.core.MediaType;
/*
* Extension of the REST MediaType with 2 new types from the RESTCONF standard RFC 8040.
*
* Currently (1.14) the XML Media Type is not supported by the RESTCONF server in ONOS
*/
public class MediaTypeRestconf extends MediaType {
public static final String APPLICATION_YANG_DATA_XML = "application/yang-data+xml";
public static final MediaType APPLICATION_YANG_DATA_XML_TYPE = new MediaType("application", "yang-data+xml");
public static final String APPLICATION_YANG_DATA_JSON = "application/yang-data+json";
public static final MediaType APPLICATION_YANG_DATA_JSON_TYPE = new MediaType("application", "yang-data+json");
}

View File

@ -0,0 +1,50 @@
/*
* Copyright 2018-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.restconf.api;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
@Provider
@Produces(MediaTypeRestconf.APPLICATION_YANG_DATA_JSON)
public class RestconfJsonBodyWriter implements MessageBodyWriter<ObjectNode> {
private ObjectMapper mapper = new ObjectMapper();
@Override
public boolean isWriteable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return type == ObjectNode.class;
}
@Override
public void writeTo(ObjectNode node, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders,
OutputStream entityStream) throws IOException {
mapper.writer().writeValue(entityStream, node);
entityStream.flush();
}
}

View File

@ -16,6 +16,7 @@
package org.onosproject.protocol.restconf.server.rpp;
import org.onlab.rest.AbstractWebApplication;
import org.onosproject.restconf.api.RestconfJsonBodyWriter;
import java.util.Set;
@ -26,6 +27,9 @@ public class RestconfProtocolProxy extends AbstractWebApplication {
@Override
public Set<Class<?>> getClasses() {
return getClasses(RestconfWebResource.class);
return getClasses(
RestconfWebResource.class,
RestconfJsonBodyWriter.class
);
}
}

View File

@ -20,6 +20,7 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.glassfish.jersey.server.ChunkedOutput;
import org.onosproject.rest.AbstractWebResource;
import org.onosproject.restconf.api.MediaTypeRestconf;
import org.onosproject.restconf.api.RestconfError;
import org.onosproject.restconf.api.RestconfException;
import org.onosproject.restconf.api.RestconfRpcOutput;
@ -84,7 +85,7 @@ public class RestconfWebResource extends AbstractWebResource {
* @return HTTP response - 200, 404 or 500
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
@Produces(MediaTypeRestconf.APPLICATION_YANG_DATA_JSON)
@Path("data/{identifier : .+}")
public Response handleGetRequest(@PathParam("identifier") String uriString) {
log.debug("handleGetRequest: {}", uriString);
@ -102,19 +103,24 @@ public class RestconfWebResource extends AbstractWebResource {
.errorAppTag("handleGetRequest")
.build();
return Response.status(NOT_FOUND)
.entity(RestconfError.wrapErrorAsJson(Arrays.asList(error))).build();
.entity(RestconfError.wrapErrorAsJson(Arrays.asList(error)))
.build();
}
return ok(node).build();
return Response.ok(node)
.build();
} catch (RestconfException e) {
log.error("ERROR: handleGetRequest: {}", e.getMessage());
log.debug("Exception in handleGetRequest:", e);
return Response.status(e.getResponse().getStatus()).entity(e.toRestconfErrorJson()).build();
return Response.status(e.getResponse().getStatus())
.entity(e.toRestconfErrorJson())
.build();
} catch (Exception e) {
RestconfError error = RestconfError
.builder(RestconfError.ErrorType.APPLICATION, RestconfError.ErrorTag.OPERATION_FAILED)
.errorMessage(e.getMessage()).errorAppTag("handlePostRequest").build();
return Response.status(INTERNAL_SERVER_ERROR)
.entity(RestconfError.wrapErrorAsJson(Arrays.asList(error))).build();
.entity(RestconfError.wrapErrorAsJson(Arrays.asList(error)))
.build();
}
}
@ -134,7 +140,7 @@ public class RestconfWebResource extends AbstractWebResource {
* @return A string data stream over HTTP keep-alive session
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
@Produces(MediaTypeRestconf.APPLICATION_YANG_DATA_JSON)
@Path("streams/{streamId}")
public ChunkedOutput<String> handleNotificationRegistration(@PathParam("streamId") String streamId,
@Context HttpServletRequest request) {
@ -164,8 +170,8 @@ public class RestconfWebResource extends AbstractWebResource {
* @return HTTP response
*/
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Consumes({MediaTypeRestconf.APPLICATION_YANG_DATA_JSON, MediaType.APPLICATION_JSON})
@Produces(MediaTypeRestconf.APPLICATION_YANG_DATA_JSON)
@Path("data")
public Response handlePostDatastore(InputStream stream) {
@ -184,8 +190,8 @@ public class RestconfWebResource extends AbstractWebResource {
* @return HTTP response
*/
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Consumes({ MediaTypeRestconf.APPLICATION_YANG_DATA_JSON, MediaType.APPLICATION_JSON })
@Produces(MediaTypeRestconf.APPLICATION_YANG_DATA_JSON)
@Path("data/{identifier : .+}")
public Response handlePostRequest(@PathParam("identifier") String uriString,
InputStream stream) {
@ -231,8 +237,8 @@ public class RestconfWebResource extends AbstractWebResource {
* @return RPC output
*/
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Consumes({ MediaTypeRestconf.APPLICATION_YANG_DATA_JSON, MediaType.APPLICATION_JSON })
@Produces(MediaTypeRestconf.APPLICATION_YANG_DATA_JSON)
@Path("operations/{rpc : .+}")
public Response handleRpcRequest(@PathParam("rpc") String rpcName,
InputStream rpcInput,
@ -288,8 +294,8 @@ public class RestconfWebResource extends AbstractWebResource {
* @return HTTP response
*/
@PUT
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Consumes({ MediaTypeRestconf.APPLICATION_YANG_DATA_JSON, MediaType.APPLICATION_JSON })
@Produces(MediaTypeRestconf.APPLICATION_YANG_DATA_JSON)
@Path("data/{identifier : .+}")
public Response handlePutRequest(@PathParam("identifier") String uriString,
InputStream stream) {
@ -335,7 +341,7 @@ public class RestconfWebResource extends AbstractWebResource {
* @return HTTP response
*/
@DELETE
@Produces(MediaType.APPLICATION_JSON)
@Produces(MediaTypeRestconf.APPLICATION_YANG_DATA_JSON)
@Path("data/{identifier : .+}")
public Response handleDeleteRequest(@PathParam("identifier") String uriString) {
log.debug("handleDeleteRequest: {}", uriString);
@ -364,8 +370,8 @@ public class RestconfWebResource extends AbstractWebResource {
* @return HTTP response
*/
@PATCH
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Consumes({ MediaTypeRestconf.APPLICATION_YANG_DATA_JSON, MediaType.APPLICATION_JSON })
@Produces(MediaTypeRestconf.APPLICATION_YANG_DATA_JSON)
@Path("data/{identifier : .+}")
public Response handlePatchRequest(@PathParam("identifier") String uriString,
InputStream stream) {
@ -412,8 +418,8 @@ public class RestconfWebResource extends AbstractWebResource {
* @return HTTP response
*/
@PATCH
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Consumes({ MediaTypeRestconf.APPLICATION_YANG_DATA_JSON, MediaType.APPLICATION_JSON })
@Produces(MediaTypeRestconf.APPLICATION_YANG_DATA_JSON)
@Path("data")
public Response handlePatchDatastore(InputStream stream) {
log.debug("handlePatchDatastore");