Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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 @@ -1265,16 +1265,18 @@ else if (ComparisonOperator.compare(arguments[0], arguments[1], null) > 0)
// ===== PARSE-URL

public static class ParseUrl extends AbstractFunction {
public ParseUrl() { super("parse-url", 1,1);}
public ParseUrl() { super("parse-url", 1, 2); }

public JsonNode call(JsonNode input, JsonNode[] arguments) {
if (arguments[0].isNull())
if (arguments.length < 1 || arguments[0].isNull())
return NullNode.instance;

String urlString = arguments[0].asText();
boolean throwOnFailure = arguments.length < 2 || arguments[1].asBoolean();

try {
URL aURL = new URL(arguments[0].asText());

URL aURL = new URL(urlString);
final ObjectNode objectNode = NodeUtils.mapper.createObjectNode();
if (aURL.getHost() != null && !aURL.getHost().isEmpty())
objectNode.put("host", aURL.getHost());
Expand Down Expand Up @@ -1303,8 +1305,17 @@ public JsonNode call(JsonNode input, JsonNode[] arguments) {
if(aURL.getUserInfo() != null && !aURL.getUserInfo().isEmpty())
objectNode.put("userinfo", aURL.getUserInfo());
return objectNode;
} catch (MalformedURLException | UnsupportedEncodingException e) {
throw new JsltException("Can't parse " + urlString, e);
} catch (Exception e) {
if (throwOnFailure) {
throw new JsltException("Can't parse " + urlString, e);
} else {
final ObjectNode errorNode = NodeUtils.mapper.createObjectNode();
final Class errorClass = e.getClass();
errorNode.put("error", errorClass.getName());
errorNode.put("message", e.getMessage());
errorNode.put("input", urlString);
return errorNode;
}
}
}
}
Expand Down
33 changes: 33 additions & 0 deletions core/src/test/resources/query-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -460,3 +460,36 @@ tests:
"port": 8443,
"scheme": "https"
}

# parse-url tests with throwOnFailure set to true should behave as above

- input:
query: parse-url("https://example.com:8443", true)
output: |
{
"host": "example.com",
"port": 8443,
"scheme": "https"
}

# parse-url tests with throwOnFailure set to false should behave as above for good cases

- input:
query: parse-url("https://example.com:8443", false)
output: |
{
"host": "example.com",
"port": 8443,
"scheme": "https"
}

# parse-url tests with throwOnFailure set to false should return an error object for bad cases

- input:
query: parse-url("this-is-an-invalid-url", false)
output: |
{
"error": "java.net.MalformedURLException",
"message": "no protocol: this-is-an-invalid-url",
"input": "this-is-an-invalid-url"
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need a test of what happens if the second argument is not a boolean. IMHO that should be considered an error: ie, throw an exception.

We also need a test of null handling, with and without the second parameter. (Should have had a null test already, sorry.) I think null input should lead to null output, regardless of the value of the second parameter.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am unsure how you typically tests for failures. Do you have an example? I looked in the query-tests.yaml and found no obvious cases to me

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See function-error-tests.json for examples.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added tests

38 changes: 37 additions & 1 deletion functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -826,10 +826,42 @@ format-time(null, "yyyy-MM-dd") => null

## Miscellaneous functions

### _parse-url(url) -> object_
### _parse-url(url, throwOnFailure?) -> object_

Parses `url` and returns an object with keys [`scheme`, `userinfo`, `host`, `port` `path`, `query`, `parameters`, `fragment` ]

If the optional `throwOnFailure` argument is not specified invalid URLs will generate an exception. If `throwOnFailure` is set to `false` the `parse-url` returns
an object indicating an error occurred.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to document the shape of that object, and have an example.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added some examples below but I agree we could add more documentation on the shape both when good and bad input

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated with more detaild examples.

#### Example of valid URL response

```json
{
"host": "example.com",
"port": 8080,
"path": "/examples/",
"scheme": "https",
"query": "x=1&y=",
"parameters": {
"x": ["1"],
"y": [null]
},
"fragment": "footer",
"userinfo": "myname:mypwd"
}
```

#### Example of invalid URL response with throwOnFailure=false

```json
{
"error": "java.net.MalformedURLException",
"message": "no protocol: this-is-an-invalid-url",
"input": "this-is-an-invalid-url"
}
```

#### Examples
```
parse-url("http://example.com").scheme => "http"
parse-url("http://example.com").host => "example.com"
Expand All @@ -841,4 +873,8 @@ parse-url("https://www.example.com/?aa=1&aa=2&bb=&cc").parameters.bb => [null]
parse-url("https://www.example.com/?aa=1&aa=2&bb=&cc").parameters.cc => [null]
parse-url("ftp://username:password@host.com/").userinfo => "username:password"
parse-url("https://example.com:8443").port => 8443

parse-url("this-is-an-invalid-url", false).error => "java.net.MalformedURLException"
parse-url("this-is-an-invalid-url", false).message => "no protocol: this-is-an-invalid-url"
parse-url("this-is-an-invalid-url", false).input => "this-is-an-invalid-url"
```