use of com.helger.commons.mime.IMimeType in project ph-web by phax.
the class MockHttpServletResponse method setContentType.
public void setContentType(@Nullable final String sContentType) {
m_sContentType = sContentType;
if (sContentType != null) {
try {
final IMimeType aContentType = MimeTypeParser.parseMimeType(sContentType);
final String sEncoding = MimeTypeHelper.getCharsetNameFromMimeType(aContentType);
if (sEncoding != null)
setCharacterEncoding(sEncoding);
} catch (final MimeTypeParserException ex) {
LOGGER.warn("Passed content type '" + sContentType + "' cannot be parsed as a MIME type");
}
}
}
use of com.helger.commons.mime.IMimeType in project phase4 by phax.
the class AS4IncomingHandler method parseAS4Message.
public static void parseAS4Message(@Nonnull final IAS4IncomingAttachmentFactory aIAF, @Nonnull @WillNotClose final AS4ResourceHelper aResHelper, @Nonnull final IAS4IncomingMessageMetadata aMessageMetadata, @Nonnull @WillClose final InputStream aPayloadIS, @Nonnull final HttpHeaderMap aHttpHeaders, @Nonnull final IAS4ParsedMessageCallback aCallback, @Nullable final IAS4IncomingDumper aIncomingDumper) throws Phase4Exception, IOException, MessagingException, WSSecurityException {
// Determine content type
final String sContentType = aHttpHeaders.getFirstHeaderValue(CHttpHeader.CONTENT_TYPE);
if (StringHelper.hasNoText(sContentType))
throw new Phase4Exception("Content-Type header is missing");
if (LOGGER.isDebugEnabled())
LOGGER.debug("Received Content-Type string: '" + sContentType + "'");
final IMimeType aContentType = MimeTypeParser.safeParseMimeType(sContentType);
if (LOGGER.isDebugEnabled())
LOGGER.debug("Received Content-Type object: " + aContentType);
if (aContentType == null)
throw new Phase4Exception("Failed to parse Content-Type '" + sContentType + "'");
final IMimeType aPlainContentType = aContentType.getCopyWithoutParameters();
// Fallback to global dumper if none is provided
final IAS4IncomingDumper aRealIncomingDumper = aIncomingDumper != null ? aIncomingDumper : AS4DumpManager.getIncomingDumper();
Document aSoapDocument = null;
ESoapVersion eSoapVersion = null;
final ICommonsList<WSS4JAttachment> aIncomingAttachments = new CommonsArrayList<>();
final Wrapper<OutputStream> aDumpOSHolder = new Wrapper<>();
if (aPlainContentType.equals(AS4RequestHandler.MT_MULTIPART_RELATED)) {
// MIME message
if (LOGGER.isDebugEnabled())
LOGGER.debug("Received MIME message");
final String sBoundary = aContentType.getParameterValueWithName("boundary");
if (StringHelper.hasNoText(sBoundary))
throw new Phase4Exception("Content-Type '" + sContentType + "' misses 'boundary' parameter");
if (LOGGER.isDebugEnabled())
LOGGER.debug("MIME Boundary: '" + sBoundary + "'");
// Ensure the stream gets closed correctly
try (final InputStream aRequestIS = AS4DumpManager.getIncomingDumpAwareInputStream(aRealIncomingDumper, aPayloadIS, aMessageMetadata, aHttpHeaders, aDumpOSHolder)) {
// PARSING MIME Message via MultipartStream
final MultipartStream aMulti = new MultipartStream(aRequestIS, sBoundary.getBytes(StandardCharsets.ISO_8859_1), (MultipartProgressNotifier) null);
int nIndex = 0;
while (true) {
final boolean bHasNextPart = nIndex == 0 ? aMulti.skipPreamble() : aMulti.readBoundary();
if (!bHasNextPart)
break;
if (LOGGER.isDebugEnabled())
LOGGER.debug("Found MIME part #" + nIndex);
try (final MultipartItemInputStream aBodyPartIS = aMulti.createInputStream()) {
// Read headers AND content
final MimeBodyPart aBodyPart = new MimeBodyPart(aBodyPartIS);
if (nIndex == 0) {
// First MIME part -> SOAP document
if (LOGGER.isDebugEnabled())
LOGGER.debug("Parsing first MIME part as SOAP document");
// Read SOAP document
aSoapDocument = DOMReader.readXMLDOM(aBodyPart.getInputStream());
IMimeType aPlainPartMT = MimeTypeParser.safeParseMimeType(aBodyPart.getContentType());
if (aPlainPartMT != null)
aPlainPartMT = aPlainPartMT.getCopyWithoutParameters();
// Determine SOAP version from MIME part content type
eSoapVersion = ESoapVersion.getFromMimeTypeOrNull(aPlainPartMT);
if (eSoapVersion != null && LOGGER.isDebugEnabled())
LOGGER.debug("Determined SOAP version " + eSoapVersion + " from Content-Type");
if (eSoapVersion == null && aSoapDocument != null) {
// Determine SOAP version from the read document
eSoapVersion = ESoapVersion.getFromNamespaceURIOrNull(XMLHelper.getNamespaceURI(aSoapDocument));
if (eSoapVersion != null && LOGGER.isDebugEnabled())
LOGGER.debug("Determined SOAP version " + eSoapVersion + " from XML root element namespace URI");
}
} else {
// MIME Attachment (index is gt 0)
if (LOGGER.isDebugEnabled())
LOGGER.debug("Parsing MIME part #" + nIndex + " as attachment");
final WSS4JAttachment aAttachment = aIAF.createAttachment(aBodyPart, aResHelper);
aIncomingAttachments.add(aAttachment);
}
}
nIndex++;
}
}
if (LOGGER.isDebugEnabled())
LOGGER.debug("Read MIME message with " + aIncomingAttachments.size() + " attachment(s)");
} else {
if (LOGGER.isDebugEnabled())
LOGGER.debug("Received plain message");
// Expect plain SOAP - read whole request to DOM
// Note: this may require a huge amount of memory for large requests
aSoapDocument = DOMReader.readXMLDOM(AS4DumpManager.getIncomingDumpAwareInputStream(aRealIncomingDumper, aPayloadIS, aMessageMetadata, aHttpHeaders, aDumpOSHolder));
if (LOGGER.isDebugEnabled())
if (aSoapDocument != null)
LOGGER.debug("Successfully parsed payload as XML");
else
LOGGER.debug("Failed to parse payload as XML");
if (aSoapDocument != null) {
// Determine SOAP version from the read document
eSoapVersion = ESoapVersion.getFromNamespaceURIOrNull(XMLHelper.getNamespaceURI(aSoapDocument));
if (eSoapVersion != null && LOGGER.isDebugEnabled())
LOGGER.debug("Determined SOAP version " + eSoapVersion + " from XML root element namespace URI");
}
if (eSoapVersion == null) {
// Determine SOAP version from content type
eSoapVersion = ESoapVersion.getFromMimeTypeOrNull(aPlainContentType);
if (eSoapVersion != null && LOGGER.isDebugEnabled())
LOGGER.debug("Determined SOAP version " + eSoapVersion + " from Content-Type");
}
}
try {
if (aSoapDocument == null) {
// We don't have a SOAP document
throw new Phase4Exception(eSoapVersion == null ? "Failed to parse incoming message!" : "Failed to parse incoming SOAP " + eSoapVersion.getVersion() + " document!");
}
if (eSoapVersion == null) {
// We're missing a SOAP version
throw new Phase4Exception("Failed to determine SOAP version of XML document!");
}
aCallback.handle(aHttpHeaders, aSoapDocument, eSoapVersion, aIncomingAttachments);
} finally {
// Here, the incoming dump is finally ready closed and usable
if (aRealIncomingDumper != null && aDumpOSHolder.isSet())
try {
aRealIncomingDumper.onEndRequest(aMessageMetadata);
} catch (final Exception ex) {
LOGGER.error("IncomingDumper.onEndRequest failed. Dumper=" + aRealIncomingDumper + "; MessageMetadata=" + aMessageMetadata, ex);
}
}
}
use of com.helger.commons.mime.IMimeType in project ph-web by phax.
the class UnifiedResponse method applyToResponse.
public final void applyToResponse(@Nonnull final HttpServletResponse aHttpResponse) throws IOException {
ValueEnforcer.notNull(aHttpResponse, "HttpResponse");
// Apply all collected headers
for (final Map.Entry<String, ICommonsList<String>> aEntry : m_aResponseHeaderMap) {
final String sHeaderName = aEntry.getKey();
int nIndex = 0;
for (final String sHeaderValue : aEntry.getValue()) {
// Ensure single line values
final String sUnifiedHeaderValue = m_bHttpHeaderValuesUnified ? HttpHeaderMap.getUnifiedValue(sHeaderValue, m_bHttpHeaderValuesQuoteIfNecessary) : sHeaderValue;
if (nIndex == 0)
aHttpResponse.setHeader(sHeaderName, sUnifiedHeaderValue);
else
aHttpResponse.addHeader(sHeaderName, sUnifiedHeaderValue);
++nIndex;
}
}
final boolean bIsRedirect = isRedirectDefined();
final boolean bHasStatusCode = isStatusCodeDefined();
if (bIsRedirect) {
if (bHasStatusCode)
logWarn("Ignoring provided status code because a redirect is specified!");
if (!m_bAllowContentOnRedirect) {
if (m_aCacheControl != null)
logInfo("Ignoring provided Cache-Control because a redirect is specified!");
if (m_sContentDispositionFilename != null)
logWarn("Ignoring provided Content-Dispostion filename because a redirect is specified!");
if (m_aMimeType != null)
logWarn("Ignoring provided MimeType because a redirect is specified!");
if (m_aCharset != null)
logWarn("Ignoring provided charset because a redirect is specified!");
if (hasContent())
logWarn("Ignoring provided content because a redirect is specified!");
}
// Note: After using this method, the response should be
// considered to be committed and should not be written to.
String sRealTargetURL;
if (ServletSettings.isEncodeURLs()) {
try {
sRealTargetURL = aHttpResponse.encodeRedirectURL(m_sRedirectTargetUrl);
} catch (final IllegalArgumentException ex) {
// Happens e.g. if "http://server/../" is requested
LOGGER.warn("Failed to encode redirect target URL '" + m_sRedirectTargetUrl + "': " + ex.getMessage());
sRealTargetURL = m_sRedirectTargetUrl;
}
} else
sRealTargetURL = m_sRedirectTargetUrl;
if (LOGGER.isDebugEnabled())
LOGGER.debug("Response is a redirect to '" + sRealTargetURL + "' using mode " + m_eRedirectMode);
switch(m_eRedirectMode) {
case DEFAULT:
aHttpResponse.sendRedirect(sRealTargetURL);
break;
case POST_REDIRECT_GET:
if (m_eHttpVersion.is10()) {
// For HTTP 1.0 send 302
aHttpResponse.setStatus(HttpServletResponse.SC_FOUND);
} else {
// For HTTP 1.1 send 303
aHttpResponse.setStatus(HttpServletResponse.SC_SEE_OTHER);
}
// Set the location header
aHttpResponse.addHeader(CHttpHeader.LOCATION, sRealTargetURL);
break;
default:
throw new IllegalStateException("Unimplemented redirect mode " + m_eRedirectMode + "!");
}
if (!m_bAllowContentOnRedirect)
return;
}
if (bHasStatusCode) {
if (bIsRedirect)
logWarn("Overriding provided redirect because a status code is specified!");
if (!m_bAllowContentOnStatusCode) {
if (m_aCacheControl != null)
logInfo("Ignoring provided Cache-Control because a status code is specified!");
if (m_sContentDispositionFilename != null)
logWarn("Ignoring provided Content-Dispostion filename because a status code is specified!");
if (m_aMimeType != null)
logWarn("Ignoring provided MimeType because a status code is specified!");
if (m_aCharset != null)
logWarn("Ignoring provided charset because a status code is specified!");
if (hasContent())
logWarn("Ignoring provided content because a status code is specified!");
}
if (m_nStatusCode == HttpServletResponse.SC_UNAUTHORIZED && !m_aResponseHeaderMap.containsHeaders(CHttpHeader.WWW_AUTHENTICATE))
logWarn("Status code UNAUTHORIZED (401) is returned, but no " + CHttpHeader.WWW_AUTHENTICATE + " HTTP response header is set!");
// Content may be present so, sendError is not an option here!
if (m_nStatusCode >= HttpServletResponse.SC_BAD_REQUEST && m_aContentArray == null) {
// It's an error
// Note: After using this method, the response should be considered
// to be committed and should not be written to.
aHttpResponse.sendError(m_nStatusCode);
} else {
// It's a status message "only"
// Note: The container clears the buffer and sets the Location
// header, preserving cookies and other headers.
aHttpResponse.setStatus(m_nStatusCode);
}
if (!m_bAllowContentOnStatusCode)
return;
if (!hasContent()) {
// continue - would produce some warnings
return;
}
}
// Verify only if is a response with content
_verifyCachingIntegrity();
if (m_aCacheControl != null) {
final String sCacheControlValue = m_aCacheControl.getAsHTTPHeaderValue();
if (StringHelper.hasText(sCacheControlValue))
aHttpResponse.setHeader(CHttpHeader.CACHE_CONTROL, sCacheControlValue);
else
logWarn("An empty Cache-Control was provided!");
}
if (m_sContentDispositionFilename != null) {
final StringBuilder aSB = new StringBuilder();
if (m_aRequestBrowserInfo != null && m_aRequestBrowserInfo.getBrowserType() == EBrowserType.IE && m_aRequestBrowserInfo.getVersion().getMajor() <= 8) {
// Special case for IE <= 8
final Charset aCharsetToUse = m_aCharset != null ? m_aCharset : StandardCharsets.UTF_8;
aSB.append(m_eContentDispositionType.getID()).append("; filename=").append(URLHelper.urlEncode(m_sContentDispositionFilename, aCharsetToUse));
} else {
// Filename needs to be surrounded with double quotes (single quotes
// don't work).
aSB.append(m_eContentDispositionType.getID()).append("; filename=\"").append(m_sContentDispositionFilename).append('"');
// Check if we need an UTF-8 filename
// http://stackoverflow.com/questions/93551/how-to-encode-the-filename-parameter-of-content-disposition-header-in-http/6745788#6745788
final String sRFC5987Filename = RFC5987Encoder.getRFC5987EncodedUTF8(m_sContentDispositionFilename);
if (!sRFC5987Filename.equals(m_sContentDispositionFilename))
aSB.append("; filename*=UTF-8''").append(sRFC5987Filename);
}
aHttpResponse.setHeader(CHttpHeader.CONTENT_DISPOSITION, aSB.toString());
if (m_aMimeType == null) {
logWarn("Content-Disposition is specified but no MimeType is set. Using the default download MimeType.");
aHttpResponse.setContentType(CMimeType.APPLICATION_FORCE_DOWNLOAD.getAsString());
}
}
// Mime type
if (m_aMimeType != null) {
final String sMimeType = m_aMimeType.getAsString();
// Check with request accept mime types
final QValue aQuality = m_aAcceptMimeTypeList.getQValueOfMimeType(m_aMimeType);
if (aQuality.isMinimumQuality()) {
final ICommonsOrderedMap<IMimeType, QValue> aBetterValues = m_aAcceptMimeTypeList.getAllQValuesGreaterThan(aQuality.getQuality());
logError("MimeType '" + sMimeType + "' is not at all supported by the request. Allowed values are: " + _getAsStringMimeTypes(aBetterValues));
} else if (aQuality.isLowValue()) {
// only in the debug version
if (GlobalDebug.isDebugMode()) {
// Inform if the quality of the request is <= 50%!
final ICommonsOrderedMap<IMimeType, QValue> aBetterValues = m_aAcceptMimeTypeList.getAllQValuesGreaterThan(aQuality.getQuality());
if (!aBetterValues.isEmpty())
logWarn("MimeType '" + sMimeType + "' is not best supported by the request (" + aQuality + "). Better MimeTypes are: " + _getAsStringMimeTypes(aBetterValues));
}
}
aHttpResponse.setContentType(sMimeType);
} else {
logWarn("No MimeType present");
}
// Charset
if (m_aCharset != null) {
final String sCharset = m_aCharset.name();
if (m_aMimeType == null)
logWarn("If no MimeType present, the client cannot get notified about the character encoding '" + sCharset + "'");
// Check with request charset
final QValue aQuality = m_aAcceptCharsetList.getQValueOfCharset(sCharset);
if (aQuality.isMinimumQuality()) {
final ICommonsOrderedMap<String, QValue> aBetterValues = m_aAcceptCharsetList.getAllQValuesGreaterThan(aQuality.getQuality());
logError("Character encoding '" + sCharset + "' is not at all supported by the request. Allowed values are: " + _getAsStringText(aBetterValues));
} else if (aQuality.isLowValue()) {
// Inform if the quality of the request is <= 50%!
final ICommonsOrderedMap<String, QValue> aBetterValues = m_aAcceptCharsetList.getAllQValuesGreaterThan(aQuality.getQuality());
if (!aBetterValues.isEmpty())
logWarn("Character encoding '" + sCharset + "' is not best supported by the request (" + aQuality + "). Better charsets are: " + _getAsStringText(aBetterValues));
}
aHttpResponse.setCharacterEncoding(sCharset);
} else if (m_aMimeType == null) {
logWarn("Also no character encoding present");
} else
switch(m_aMimeType.getContentType()) {
case TEXT:
case MULTIPART:
logWarn("A character encoding for MimeType '" + m_aMimeType.getAsString() + "' is appreciated.");
break;
default:
// Do we need character encoding here as well???
break;
}
// Add all cookies
if (m_aCookies != null)
for (final Cookie aCookie : m_aCookies.values()) aHttpResponse.addCookie(aCookie);
// Write the body to the response
_applyContent(aHttpResponse, bHasStatusCode);
}
use of com.helger.commons.mime.IMimeType in project phase4 by phax.
the class PModePayloadProfileJsonConverter method convertToNative.
@Nonnull
public static PModePayloadProfile convertToNative(final IJsonObject aElement) {
final String sName = aElement.getAsString(NAME);
final String sMimeType = aElement.getAsString(MIME_TYPE);
final IMimeType aMimeType;
try {
aMimeType = MimeTypeParser.parseMimeType(sMimeType);
} catch (final MimeTypeParserException ex) {
throw new IllegalArgumentException("Failed to parse MIME Type '" + sMimeType + "'", ex);
}
final String sXSDFilename = aElement.getAsString(XSD_FILENAME);
final Integer aMaxSizeKB = aElement.getAsIntObj(MAX_SIZE_KB);
final EMandatory eMandatory = EMandatory.valueOf(aElement.getAsBoolean(MANDATORY, PModePayloadProfile.DEFAULT_MANDATORY));
return new PModePayloadProfile(sName, aMimeType, sXSDFilename, aMaxSizeKB, eMandatory);
}
use of com.helger.commons.mime.IMimeType in project phase4 by phax.
the class PModePayloadProfileMicroTypeConverter method convertToNative.
@Nonnull
public PModePayloadProfile convertToNative(final IMicroElement aElement) {
final String sName = aElement.getAttributeValue(ATTR_NAME);
final String sMimeType = aElement.getAttributeValue(ATTR_MIME_TYPE);
final IMimeType aMimeType;
try {
aMimeType = MimeTypeParser.parseMimeType(sMimeType);
} catch (final MimeTypeParserException ex) {
throw new IllegalArgumentException("Failed to parse MIME Type '" + sMimeType + "'", ex);
}
final String sXSDFilename = aElement.getAttributeValue(ATTR_XSD_FILENAME);
final Integer aMaxSizeKB = aElement.getAttributeValueWithConversion(ATTR_MAX_SIZE_KB, Integer.class);
final EMandatory eMandatory = EMandatory.valueOf(aElement.getAttributeValueAsBool(ATTR_MANDATORY, PModePayloadProfile.DEFAULT_MANDATORY));
return new PModePayloadProfile(sName, aMimeType, sXSDFilename, aMaxSizeKB, eMandatory);
}
Aggregations