import javax.ws.rs.core.EntityTag;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.ParamConverter;
import org.opendaylight.restconf.nb.rfc8040.databind.jaxrs.QueryParams;
import org.opendaylight.restconf.nb.rfc8040.legacy.ErrorTags;
import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
+import org.opendaylight.restconf.server.api.ConfigurationMetadata;
import org.opendaylight.restconf.server.api.DataGetResult;
import org.opendaylight.restconf.server.api.DataPostResult;
import org.opendaylight.restconf.server.api.DataPostResult.CreateResource;
final var builder = Response.status(Status.OK)
.entity(result.payload())
.cacheControl(NO_CACHE);
- final var etag = result.entityTag();
- if (etag != null) {
- builder.tag(new EntityTag(etag.value(), etag.weak()));
- }
- final var lastModified = result.lastModified();
- if (lastModified != null) {
- builder.lastModified(Date.from(lastModified));
- }
+ fillConfigurationMetadata(builder, result);
return builder.build();
}
});
}
+ private static void fillConfigurationMetadata(final ResponseBuilder builder, final ConfigurationMetadata metadata) {
+ final var etag = metadata.entityTag();
+ if (etag != null) {
+ builder.tag(new EntityTag(etag.value(), etag.weak()));
+ }
+ final var lastModified = metadata.lastModified();
+ if (lastModified != null) {
+ builder.lastModified(Date.from(lastModified));
+ }
+ }
+
/**
* Partially modify the target data store, as defined in
* <a href="https://www.rfc-editor.org/rfc/rfc8040#section-4.6.1">RFC8040, section 4.6.1</a>.
@Override
Response transform(final DataPostResult result) {
if (result instanceof CreateResource createResource) {
- return Response.created(uriInfo.getBaseUriBuilder()
- .path("data")
- .path(createResource.createdPath())
- .build())
- .build();
+ final var builder = Response.created(uriInfo.getBaseUriBuilder()
+ .path("data")
+ .path(createResource.createdPath())
+ .build());
+ fillConfigurationMetadata(builder, createResource);
+ return builder.build();
}
if (result instanceof InvokeOperation invokeOperation) {
final var output = invokeOperation.output();
import static java.util.Objects.requireNonNull;
-import org.eclipse.jdt.annotation.NonNullByDefault;
+import java.time.Instant;
+import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
* Result of a {@code POST} request as defined in
* <a href="https://www.rfc-editor.org/rfc/rfc8040#section-4.4">RFC8040 section 4.4</a>.
*/
-@NonNullByDefault
public sealed interface DataPostResult {
/**
* Result of a {@code POST} request in as defined in
* <a href="https://www.rfc-editor.org/rfc/rfc8040#section-4.4.1">RFC8040 Create Resource Mode</a>.
*
* @param createdPath API path of the newly-created resource
+ * @param entityTag response {@code ETag} header, or {@code null} if not applicable
+ * @param lastModified response {@code Last-Modified} header, or {@code null} if not applicable
*/
- // FIXME: use ApiPath instead of String
- record CreateResource(String createdPath) implements DataPostResult {
+ record CreateResource(
+ // FIXME: use ApiPath instead of String
+ @NonNull String createdPath,
+ @Nullable EntityTag entityTag,
+ @Nullable Instant lastModified) implements DataPostResult, ConfigurationMetadata {
public CreateResource {
requireNonNull(createdPath);
}
+
+ public CreateResource(final @NonNull String createdPath) {
+ this(createdPath, null, null);
+ }
}
/**
import org.opendaylight.restconf.nb.rfc8040.databind.PatchBody;
import org.opendaylight.restconf.nb.rfc8040.databind.ResourceBody;
import org.opendaylight.restconf.nb.rfc8040.legacy.NormalizedNodePayload;
-import org.opendaylight.restconf.server.api.DataPostResult.CreateResource;
import org.opendaylight.yangtools.yang.common.Empty;
/**
* <a href="https://www.rfc-editor.org/rfc/rfc8040#section-3.3">RESTCONF API Resource</a>.
*/
// FIXME: NETCONF-1207: configuration datastore should maintain ETag and Last-Modified headers, so that these can be
-// returned when PATCH/POST/PUT modify the data.
+// returned when PATCH/PUT modify the data.
@NonNullByDefault
public interface RestconfServer {
/**
*/
RestconfFuture<PatchStatusContext> dataPATCH(ApiPath identifier, PatchBody body);
- RestconfFuture<CreateResource> dataPOST(ChildBody body, Map<String, String> queryParameters);
+ RestconfFuture<DataPostResult.CreateResource> dataPOST(ChildBody body, Map<String, String> queryParameters);
RestconfFuture<? extends DataPostResult> dataPOST(ApiPath identifier, DataPostBody body,
Map<String, String> queryParameters);