Skip to content

Commit

Permalink
Accept request URL in lieu of configuration file
Browse files Browse the repository at this point in the history
Replaced the --config option with a positional argument that is either a path to the JSON configuration file, as before, or the URL to a Directions or Map Matching API request.

Expand a tilde in the configuration file path when validating the arguments.

Removed a passage from the documentation that refers to a not-yet-implemented feature.
  • Loading branch information
1ec5 committed Aug 23, 2022
1 parent d6ca593 commit 8ded1f6
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 22 deletions.
13 changes: 11 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,20 @@

## 2.7.0

### Packaging

* Xcode 13.0 or above and Swift 5.5 or above are now required to build MapboxDirections from source. ([#725](https://github.com/mapbox/mapbox-directions-swift/pull/725), [#727](https://github.com/mapbox/mapbox-directions-swift/pull/727))

### Command line tool

* Removed the `--config` option. Instead, pass in either the path to a JSON configuration file or the full URL to a Mapbox Directions API or Mapbox Map Matching API request. ([#726](https://github.com/mapbox/mapbox-directions-swift/pull/726))
* When the `MAPBOX_ACCESS_TOKEN` environment variable is unset, the tool exits with an error code instead of crashing. ([#728](https://github.com/mapbox/mapbox-directions-swift/pull/728))
* The tool now connects to the API endpoint in the `MAPBOX_HOST` environment variable, if specified. ([#728](https://github.com/mapbox/mapbox-directions-swift/pull/728))

### Other changes

* Added `Waypoint.allowsSnappingToStaticallyClosedRoad` property to allow snapping the waypoint’s location to a statically (long-term) closed part of a road. ([#721](https://github.com/mapbox/mapbox-directions-swift/pull/721))
* `RouteOptions(url:)` now returns `nil` if given a Mapbox Map Matching API request URL, and `MatchOptions(url:)` returns `nil` if given a Mapbox Directions API request URL. ([#728](https://github.com/mapbox/mapbox-directions-swift/pull/728))
* When the `MAPBOX_ACCESS_TOKEN` environment variable is unset, the `mapbox-directions-swift` command line tool exits with an error code instead of crashing. ([#728](https://github.com/mapbox/mapbox-directions-swift/pull/728))
* The `mapbox-directions-swift` command line tool now connects to the API endpoint in the `MAPBOX_HOST` environment variable, if specified. ([#728](https://github.com/mapbox/mapbox-directions-swift/pull/728))

## v2.6.0

Expand Down
12 changes: 8 additions & 4 deletions CommandLineTool.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,16 @@ To connect to an API endpoint other than the default Mapbox API endpoint, set th

`mapbox-directions-swift` is a useful tool for mobile quality assurance. This tool can be used to verify a response to ensure proper Directions API integration, get a [GPX](https://wikipedia.org/wiki/GPS_Exchange_Format) trace that can be used in the Xcode Simulator, and convert a Directions API request to an Options object.

### Arguments

The sole argument is either:

* The path to a JSON file that contains a serialized `RouteOptions` or `MatchOptions`
* The URL of a Mapbox Directions API or Mapbox Map Matching API request

### Options
`--input`
An optional flag for the filepath to the input JSON. If this flag is not used, `mapbox-directions-swift` will fallback to a Directions API request. To request using specific coordinates, specify coordinates using `--waypoints` or a Directions API request using `--url`.

`--config`
An optional flag for the filepath to the JSON, containing serialized Options data.
An optional flag for the filepath to the input JSON. If this flag is not used, `mapbox-directions-swift` will fallback to a Directions API request.

`--output`
An optional flag for the filepath to save the conversion result. If no filepath is provided, the result will output to the shell. If you want a GPX trace that can be easily uploaded to Xcode, provide an output filepath with this flag.
Expand Down
47 changes: 37 additions & 10 deletions Sources/MapboxDirectionsCLI/CodingOperation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,17 @@ class CodingOperation<ResponseType : Codable & DirectionsResultsProvider, Option
return interpolatedCoordinates
}

private func requestResponse(_ directionsOptions: OptionsType) -> (Data) {
private func response(fetching directionsOptions: OptionsType) -> (Data) {
let directions = Directions(credentials: credentials)
let url = directions.url(forCalculating: directionsOptions)
return response(fetching: url)
}

private func response(fetching url: URL) -> Data {
let semaphore = DispatchSemaphore(value: 0)

var responseData: Data!

let directions = Directions(credentials: credentials)
let url = directions.url(forCalculating: directionsOptions)
let urlSession = URLSession(configuration: .ephemeral)

let task = urlSession.dataTask(with: url) { (data, response, error) in
Expand All @@ -151,20 +155,43 @@ class CodingOperation<ResponseType : Codable & DirectionsResultsProvider, Option

func execute() throws {

let config = FileManager.default.contents(atPath: NSString(string: options.configPath).expandingTildeInPath)!
let input: Data

let decoder = JSONDecoder()

let directionsOptions = try decoder.decode(OptionsType.self, from: config)
let directions: Directions
let directionsOptions: OptionsType
let requestURL: URL
if FileManager.default.fileExists(atPath: (options.config as NSString).expandingTildeInPath) {
// Assume the file is a configuration JSON file. Convert it to an options object.
let configData = FileManager.default.contents(atPath: (options.config as NSString).expandingTildeInPath)!
let decoder = JSONDecoder()
directions = Directions(credentials: credentials)
directionsOptions = try decoder.decode(OptionsType.self, from: configData)
} else if let url = URL(string: options.config) {
// Try to convert the URL to an options object.
if let parsedOptions = (RouteOptions(url: url) ?? MatchOptions(url: url)) as? OptionsType {
directionsOptions = parsedOptions
} else {
fatalError("Configuration is not a valid Mapbox Directions API or Mapbox Map Matching API request URL.")
}

// Get credentials from the request URL but fall back to the environment.
var urlWithAccessToken = URLComponents(string: url.absoluteString)!
urlWithAccessToken.queryItems = (urlWithAccessToken.queryItems ?? []) + [.init(name: "access_token", value: self.credentials.accessToken)]
let credentials = Credentials(requestURL: urlWithAccessToken.url!)

directions = Directions(credentials: credentials)
} else {
fatalError("Configuration is not a valid JSON configuration file or request URL.")
}

let input: Data
if let inputPath = options.inputPath {
input = FileManager.default.contents(atPath: NSString(string: inputPath).expandingTildeInPath)!
} else {
let response = requestResponse(directionsOptions)
requestURL = directions.url(forCalculating: directionsOptions)
let response = response(fetching: requestURL)
input = response
}

let decoder = JSONDecoder()
decoder.userInfo = [.options: directionsOptions,
.credentials: credentials]

Expand Down
10 changes: 4 additions & 6 deletions Sources/MapboxDirectionsCLI/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ import Foundation
import MapboxDirections
import ArgumentParser


struct ProcessingOptions: ParsableArguments {

@Option(name: [.short, .customLong("input")], help: "[Optional] Filepath to the input JSON. If no filepath provided - will fall back to Directions API request using locations in config file.")
var inputPath: String?

@Option(name: [.short, .customLong("config")], help: "Filepath to the JSON, containing serialized Options data.")
var configPath: String
@Argument(help: "Path to a JSON file containing serialized RouteOptions or MatchOptions properties, or the full URL of a Mapbox Directions API or Mapbox Map Matching API request.")
var config: String

@Option(name: [.short, .customLong("output")], help: "[Optional] Output filepath to save the conversion result. If no filepath provided - will output to the shell.")
var outputPath: String?
Expand Down Expand Up @@ -53,9 +52,8 @@ struct Command: ParsableCommand {
)

fileprivate static func validateInput(_ options: ProcessingOptions) throws {

guard FileManager.default.fileExists(atPath: options.configPath) else {
throw ValidationError("Options JSON file `\(options.configPath)` does not exist.")
if !FileManager.default.fileExists(atPath: (options.config as NSString).expandingTildeInPath) && URL(string: options.config) == nil {
throw ValidationError("Configuration is a nonexistent file or invalid request URL: \(options.config)")
}
}
}
Expand Down

0 comments on commit 8ded1f6

Please sign in to comment.