@@ -460,11 +460,36 @@ class ChallengeProvider @Inject() (
460
460
case None => osmQLProvider.requestTimeout
461
461
}
462
462
463
+ val modifiedQuery = rewriteQuery(ql)
464
+ logger.info(modifiedQuery)
465
+
463
466
val jsonFuture =
464
- this .ws.url(osmQLProvider.providerURL).withRequestTimeout(timeout).post(parseQuery(ql) )
467
+ this .ws.url(osmQLProvider.providerURL).withRequestTimeout(timeout).post(modifiedQuery )
465
468
jsonFuture onComplete {
466
469
case Success (result) =>
467
470
if (result.status == Status .OK ) {
471
+ val contentType = result.header(" Content-Type" )
472
+
473
+ // check that the Overpass API returned JSON
474
+ if (contentType.isDefined && contentType != Some (" application/json" )) {
475
+ this .challengeDAL.update(
476
+ Json .obj(
477
+ " status" -> Challenge .STATUS_FAILED ,
478
+ " statusMessage" -> s """
479
+ |Overpass API returned response with Content-Type: ${contentType.get}
480
+ |
481
+ |MapRoulette requires OverpassQL queries to return JSON.
482
+ |
483
+ |If your query contained [out:xml] or [out:csv], replace it with [out:json] and try again.
484
+ """ .stripMargin
485
+ ),
486
+ user
487
+ )(challenge.id)
488
+ throw new InvalidException (
489
+ s " Overpass API returned unexpected Content-Type: ${contentType.get}"
490
+ )
491
+ }
492
+
468
493
this .db.withTransaction { implicit c =>
469
494
var partial = false
470
495
val payload = result.json
@@ -730,23 +755,48 @@ class ChallengeProvider @Inject() (
730
755
}
731
756
732
757
/**
733
- * parse the query, replace various extended overpass query parameters see https://wiki.openstreetmap.org/wiki/Overpass_turbo/Extended_Overpass_Queries
734
- * Currently do not support {{bbox}} or {{center}}
758
+ * rewrite the user-provided OverpassQL query, adding output format and timeout settings if they are missing.
735
759
*
736
- * @param query The query to parse
737
- * @return
760
+ * @param query the input query as a string
761
+ * @return a modified query string
738
762
*/
739
- private def parseQuery (query : String ): String = {
763
+ private def rewriteQuery (query : String ): String = {
740
764
val osmQLProvider = config.getOSMQLProvider
741
- // User can set their own custom timeout if the want
742
- if (query.indexOf(" [out:json]" ) == 0 ) {
743
- query
744
- } else if (query.indexOf(" [timeout:" ) == 0 ) {
745
- s " [out:json] $query"
765
+ val timeout = osmQLProvider.requestTimeout.toSeconds
766
+
767
+ val split = query.trim.split(" \n " , 2 )
768
+ var (firstLine, restOfQuery) = {
769
+ split.length match {
770
+ case 0 => (" " , " " )
771
+ case 1 => (split(0 ).trim, " " )
772
+ case _ => (split(0 ).trim, split(1 ))
773
+ }
774
+ }
775
+
776
+ if (firstLine.startsWith(" [" ) && firstLine.endsWith(" ;" )) {
777
+ // first line looks like OverpassQL settings statement
778
+ // https://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL#Settings
779
+
780
+ if (! firstLine.contains(" [out:" )) {
781
+ // if no output format was given by the user, add [out:json]
782
+ firstLine = " [out:json]" + firstLine
783
+ }
784
+ if (! firstLine.contains(" [timeout:" )) {
785
+ // if no timeout was specified by the user, add one
786
+ firstLine = s " [timeout: ${timeout}] " + firstLine
787
+ }
788
+
789
+ s " ${firstLine}\n ${restOfQuery}"
746
790
} else {
747
- s " [out:json][timeout: ${osmQLProvider.requestTimeout.toSeconds}]; $query"
791
+ // first line doesn't look like OverpassQL settings, so assume no settings were provided,
792
+ // and prepend the required ones.
793
+ // NOTE: this branch will incorrectly be reached if the query started with a comment,
794
+ // or if the settings were split across multiple lines (OverpassQL allows both)
795
+ s " [out:json][timeout: ${timeout}]; \n $query"
748
796
}
749
- // execute regex matching against {{data:string}}, {{geocodeId:name}}, {{geocodeArea:name}}, {{geocodeBbox:name}}, {{geocodeCoords:name}}
797
+
798
+ // TODO: execute regex matching against {{data:string}}, {{geocodeId:name}}, {{geocodeArea:name}}, {{geocodeBbox:name}}, {{geocodeCoords:name}}
799
+ // see https://wiki.openstreetmap.org/wiki/Overpass_turbo/Extended_Overpass_Queries
750
800
}
751
801
752
802
/**
0 commit comments