Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@
<suppress checks="com.azure.tools.checkstyle.checks.GoodLoggingCheck"
files="com.azure.storage.common.implementation.StorageImplUtils.java"/>
<suppress checks="com.azure.tools.checkstyle.checks.GoodLoggingCheck" files="com.azure.core.http.ProxyOptions.java"/>
<suppress checks="com.azure.tools.checkstyle.checks.GoodLoggingCheck" files="com.azure.core.util.serializer.SerializerEncoding.java"/>

<!-- Azure Core Test -->
<suppress checks="com.azure.tools.checkstyle.checks.GoodLoggingCheck" files=".*[/\\]core[/\\]test[/\\].*\.java"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@

package com.azure.core.util.serializer;


import com.azure.core.http.HttpHeaders;
import com.azure.core.util.logging.ClientLogger;

import java.util.Map;
import java.util.TreeMap;

/**
* Supported serialization encoding formats.
Expand All @@ -20,21 +23,68 @@ public enum SerializerEncoding {
*/
XML;

private static final ClientLogger LOGGER = new ClientLogger(SerializerEncoding.class);
private static final String CONTENT_TYPE = "Content-Type";
private static final Map<String, SerializerEncoding> SUPPORTED_MIME_TYPES;
private static final TreeMap<String, SerializerEncoding> SUPPORTED_SUFFIXES;
private static final SerializerEncoding DEFAULT_ENCODING = JSON;


static {
// Encodings and suffixes from: https://tools.ietf.org/html/rfc6838
SUPPORTED_MIME_TYPES = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
SUPPORTED_MIME_TYPES.put("text/xml", XML);
SUPPORTED_MIME_TYPES.put("application/xml", XML);
SUPPORTED_MIME_TYPES.put("application/json", JSON);

SUPPORTED_SUFFIXES = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
SUPPORTED_SUFFIXES.put("xml", XML);
SUPPORTED_SUFFIXES.put("json", JSON);
}

/**
* Determines the serializer encoding to use based on the Content-Type header.
*
* @param headers the headers to check the encoding for
* @return the serializer encoding to use for the body
* @param headers the headers to check the encoding for.
* @return the serializer encoding to use for the body. {@link #JSON} if there is no Content-Type header or an
* unrecognized Content-Type encoding is returned.
*/
public static SerializerEncoding fromHeaders(HttpHeaders headers) {
String mimeContentType = headers.getValue("Content-Type");
if (mimeContentType != null) {
String[] parts = mimeContentType.split(";");
if (parts[0].equalsIgnoreCase("application/xml") || parts[0].equalsIgnoreCase("text/xml")) {
return XML;
}
final String mimeContentType = headers.getValue(CONTENT_TYPE);
if (mimeContentType == null || mimeContentType.isEmpty()) {
LOGGER.warning("'{}' not found. Returning default encoding: {}", CONTENT_TYPE, DEFAULT_ENCODING);
return DEFAULT_ENCODING;
}

final SerializerEncoding encoding = SUPPORTED_MIME_TYPES.get(mimeContentType);
if (encoding != null) {
return encoding;
}

final String[] parts = mimeContentType.split(";");
final String[] mimeTypeParts = parts[0].split("/");
if (mimeTypeParts.length != 2) {
LOGGER.warning("Content-Type '{}' does not match mime-type formatting 'type'/'subtype'. "
+ "Returning default: {}", parts[0], DEFAULT_ENCODING);
return DEFAULT_ENCODING;
}

// Check the suffix if it does not match the full types.
final String subtype = mimeTypeParts[1];
final int lastIndex = subtype.lastIndexOf("+");
if (lastIndex == -1) {
return DEFAULT_ENCODING;
}

final String mimeTypeSuffix = subtype.substring(lastIndex + 1);
final SerializerEncoding serializerEncoding = SUPPORTED_SUFFIXES.get(mimeTypeSuffix);
if (serializerEncoding != null) {
return serializerEncoding;
}

return JSON;
LOGGER.warning("Content-Type '{}' does not match any supported one. Returning default: {}",
mimeContentType, DEFAULT_ENCODING);

return DEFAULT_ENCODING;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package com.azure.core.util.serializer;

import com.azure.core.http.HttpHeaders;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

import java.util.Collections;

/**
* Tests for {@link SerializerEncoding}.
*/
class SerializerEncodingTests {
private static final String CONTENT_TYPE = "Content-Type";

@ParameterizedTest
@ValueSource(strings = {"application/xml", "application/atom+xml", "text/xml", "application/foo+XML", "TEXT/XML"})
void recognizeXml(String mimeType) {
// Arrange
HttpHeaders headers = new HttpHeaders(Collections.singletonMap(CONTENT_TYPE, mimeType));

// Act & Assert
Assertions.assertEquals(SerializerEncoding.XML, SerializerEncoding.fromHeaders(headers));
}

@ParameterizedTest
@ValueSource(strings = {"application/json", "application/kv+json", "APPLICATION/JSON", "application/FOO+JSON"})
void recognizeJson(String mimeType) {
// Arrange
HttpHeaders headers = new HttpHeaders(Collections.singletonMap(CONTENT_TYPE, mimeType));

// Act & Assert
Assertions.assertEquals(SerializerEncoding.JSON, SerializerEncoding.fromHeaders(headers));
}

@Test
void defaultNoContentType() {
// Arrange
HttpHeaders headers = new HttpHeaders(Collections.singletonMap("Http-Method", "GET"));

// Act & Assert
Assertions.assertEquals(SerializerEncoding.JSON, SerializerEncoding.fromHeaders(headers));
}

@ParameterizedTest
@ValueSource(strings = {"application/binary", "invalid-mime-type"})
void defaultUnsupportedType(String mimeType) {
// Arrange
HttpHeaders headers = new HttpHeaders(Collections.singletonMap(CONTENT_TYPE, mimeType));

// Act & Assert
Assertions.assertEquals(SerializerEncoding.JSON, SerializerEncoding.fromHeaders(headers));
}
}