2 * Copyright (c) 2024 PANTHEON.tech, s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.restconf.nb.rfc8040;
10 import static java.util.Objects.requireNonNull;
12 import com.google.common.collect.ImmutableMap;
13 import org.eclipse.jdt.annotation.NonNullByDefault;
14 import org.opendaylight.restconf.api.HttpStatusCode;
15 import org.opendaylight.yangtools.yang.common.ErrorTag;
18 * Mapping of {@link ErrorTag}s to {@link HttpStatusCode}s.
21 public enum ErrorTagMapping {
23 * Mapping specified by <a href="https://www.rfc-editor.org/rfc/rfc8040#page-74">RFC8040</a>:
24 * {@link ErrorTag#DATA_MISSING} is reported as {@code 409 Conflict}. This may be confusing to users, as {@code GET}
25 * requests to non-existent datastore resources do not report {@code 404 Not Found} as would be expected from any
28 RFC8040(HttpStatusCode.CONFLICT),
30 * Mapping proposed by <a href="https://www.rfc-editor.org/errata/eid5565">Errata 5565</a>:
31 * {@link ErrorTag#DATA_MISSING} is reported as {@code 404 Not Found}. This is more in-line with expectations rooted
32 * in <a href="https://www.rfc-editor.org/rfc/rfc7231#section-6.5.4">HTTP/1.1 specification</a>.
34 ERRATA_5565(HttpStatusCode.NOT_FOUND);
36 private ImmutableMap<ErrorTag, HttpStatusCode> tagToStatus;
38 ErrorTagMapping(final HttpStatusCode dataMissing) {
39 tagToStatus = ImmutableMap.<ErrorTag, HttpStatusCode>builder()
40 .put(ErrorTag.IN_USE, HttpStatusCode.CONFLICT)
41 .put(ErrorTag.INVALID_VALUE, HttpStatusCode.BAD_REQUEST)
42 .put(ErrorTag.TOO_BIG, HttpStatusCode.CONTENT_TOO_LARGE)
43 .put(ErrorTag.MISSING_ATTRIBUTE, HttpStatusCode.BAD_REQUEST)
44 .put(ErrorTag.BAD_ATTRIBUTE, HttpStatusCode.BAD_REQUEST)
45 .put(ErrorTag.UNKNOWN_ATTRIBUTE, HttpStatusCode.BAD_REQUEST)
46 .put(ErrorTag.MISSING_ELEMENT, HttpStatusCode.BAD_REQUEST)
47 .put(ErrorTag.BAD_ELEMENT, HttpStatusCode.BAD_REQUEST)
48 .put(ErrorTag.UNKNOWN_ELEMENT, HttpStatusCode.BAD_REQUEST)
49 .put(ErrorTag.UNKNOWN_NAMESPACE, HttpStatusCode.BAD_REQUEST)
51 .put(ErrorTag.ACCESS_DENIED, HttpStatusCode.FORBIDDEN)
52 .put(ErrorTag.LOCK_DENIED, HttpStatusCode.CONFLICT)
53 .put(ErrorTag.RESOURCE_DENIED, HttpStatusCode.CONFLICT)
54 .put(ErrorTag.ROLLBACK_FAILED, HttpStatusCode.INTERNAL_SERVER_ERROR)
55 .put(ErrorTag.DATA_EXISTS, HttpStatusCode.CONFLICT)
56 .put(ErrorTag.DATA_MISSING, dataMissing)
58 .put(ErrorTag.OPERATION_NOT_SUPPORTED, HttpStatusCode.NOT_IMPLEMENTED)
59 .put(ErrorTag.OPERATION_FAILED, HttpStatusCode.INTERNAL_SERVER_ERROR)
60 .put(ErrorTag.PARTIAL_OPERATION, HttpStatusCode.INTERNAL_SERVER_ERROR)
61 .put(ErrorTag.MALFORMED_MESSAGE, HttpStatusCode.BAD_REQUEST)
62 .put(ErrorTags.RESOURCE_DENIED_TRANSPORT, HttpStatusCode.SERVICE_UNAVAILABLE)
67 * Return the HTTP {@link HttpStatusCode} corresponding to specified {@link ErrorTag}.
69 * @param tag Error tag to map
70 * @return A {@link HttpStatusCode}
71 * @throws NullPointerException if {@code tag} is null
73 public HttpStatusCode statusOf(final ErrorTag tag) {
74 final var known = tagToStatus.get(requireNonNull(tag));
75 return known != null ? known : HttpStatusCode.INTERNAL_SERVER_ERROR;