Skip to content

Commit

Permalink
Merge branch '2.5.x'
Browse files Browse the repository at this point in the history
  • Loading branch information
graemerocher committed May 28, 2015
2 parents 8149282 + c62b102 commit 1544656
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class DefaultAcceptHeaderParser implements AcceptHeaderParser {
MimeType appXml = mimes.find { MimeType it -> it.name == MimeType.XML.name }
if (textXml && appXml) {
// take the largest q value
appXml.parameters.q = [textXml.parameters.q.toBigDecimal(), appXml.parameters.q.toBigDecimal()].max()
appXml.parameters.q = [textXml.qualityAsNumber, appXml.qualityAsNumber].max()

mimes.remove(textXml)
}
Expand All @@ -103,9 +103,9 @@ class DefaultAcceptHeaderParser implements AcceptHeaderParser {
// prioritise more specific XML types like xhtml+xml if they are of equal quality
def specificTypes = mimes.findAll { MimeType it -> it.name ==~ /\S+?\+xml$/ }
def appXmlIndex = mimes.indexOf(appXml)
def appXmlQuality = appXml.parameters.q.toBigDecimal()
def appXmlQuality = appXml.qualityAsNumber
for (mime in specificTypes) {
if (mime.parameters.q.toBigDecimal() < appXmlQuality) continue
if (mime.qualityAsNumber < appXmlQuality) continue

def mimeIndex = mimes.indexOf(mime)
if (mimeIndex > appXmlIndex) {
Expand Down Expand Up @@ -139,8 +139,8 @@ class DefaultAcceptHeaderParser implements AcceptHeaderParser {
class QualityComparator implements Comparator<MimeType> {

int compare(MimeType t, MimeType t1) {
def left = t.parameters.q.toBigDecimal()
def right = t1.parameters.q.toBigDecimal()
BigDecimal left = t.qualityAsNumber
BigDecimal right = t1.qualityAsNumber
if (left > right) return -1
if (left < right) return 1
return 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,15 @@ grails.mime.types = [ xml: ['text/xml', 'application/xml'],
assertEquals(['html','html','xml', 'all'], mimes.extension)
}

void testParseAcceptHeaderWithNonNumericQualityValue() {

def mimes = getAcceptHeaderParser().parse("text/html,application/xhtml+xml,application/xml;q=blah,*/*;q=0.8")

assertEquals 4, mimes.size()

assertEquals(['html','html','xml', 'all'], mimes.extension)
}

void testAcceptHeaderWithQNumberOrdering() {
def mimes = getAcceptHeaderParser().parse("text/html,application/xhtml+xml,application/xml;q=1.1,*/*;q=0.8")

Expand Down
38 changes: 34 additions & 4 deletions grails-web-common/src/main/groovy/grails/web/mime/MimeType.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ class MimeType {

private static DEFAULTS = createDefaults()
public static final String QUALITY_RATING = "1.0"
public static final BigDecimal QUALITY_RATING_NUMBER = 1.0

String name
String extension
Map<String, String> parameters = [q: QUALITY_RATING]

private BigDecimal qualityNumberField

MimeType(String name, Map params = [:]) {
this(name, null, params)
Expand All @@ -71,17 +78,23 @@ class MimeType {
parameters.putAll(params)
}

String name
String extension
Map<String, String> parameters = [q: QUALITY_RATING]

/**
* @return The quality of the Mime type
*/
String getQuality() {
return parameters.q ?: QUALITY_RATING
}

/**
* @return The quality in BigDecimal form
*/
BigDecimal getQualityAsNumber() {
if(this.qualityNumberField == null) {
this.qualityNumberField = getOrConvertQualityParameterToBigDecimal(this)
}
return this.qualityNumberField
}

/**
* @return The version of the Mime type
*/
Expand Down Expand Up @@ -144,4 +157,21 @@ class MimeType {
mimes << TEXT_JSON
mimes as MimeType[]
}

private BigDecimal getOrConvertQualityParameterToBigDecimal(MimeType mt) {
BigDecimal bd
try {
def q = mt.parameters.q
if(q == null) return QUALITY_RATING_NUMBER
else {
bd = q.toString().toBigDecimal()
// replace to avoid expensive conversion again
mt.parameters.q = bd
}
return bd
} catch (NumberFormatException e) {
bd = QUALITY_RATING_NUMBER
return bd
}
}
}

0 comments on commit 1544656

Please sign in to comment.