0

My questions seem to be as same as this question: Java equivalent of Pythons urllib.urlencode(HashMap based UrlEncode) however, is not. Because its answer is not right (or I am doing something wrong that I am not aware of).

I have this Python3 code:

def create_vxttoken_data(path_uri, expiry, reuse, shared_secret):
    # Combine the parameters into a URL-encoded string
    message = []
    message.extend([('pathURI', path_uri)])
    message.extend([('expiry', expiry)])
    message.extend([('reuse', reuse)])
    print(message)

    url_encoded_message = urlencode(message)
    print(url_encoded_message)

    # ... rest of the code

This is its output:

[('pathURI', 'http://my.domain.net/*'), ('expiry', 1553937508), ('reuse', 0)]
pathURI=http%3A%2F%2Fmy.domain.net%2F%2A&expiry=1553937508&reuse=0

I tried to write it in Kotlin. So this is my code:

fun main(args: Array<String>) {
    val queryParams = "pathURI=$PATH_URI&expiry=${expiryTime(10)}&reuse=$REUSE"
    println(queryParams)

    val encodedQueryParams = URLEncoder.encode(queryParams, Charsets.UTF_8.toString())
    println(encodedQueryParams)

    // ... rest of the code

This is its output:

pathURI=http://my.domain.net/*&expiry=1553938196&reuse=0
pathURI%3Dhttp%3A%2F%2Fmy.domain.net%2F*%26expiry%3D1553938196%26reuse%3D0

By compar of the second line of outputs you see that Kotlin/Java has converted = while Python didn't. Also, Kotlin/Java didn't translate * while Python does. I want Kotlin/Java generates output like what Python does. The rest of my code is creating a token based on this info. Consequently, my authentication fails.

Note: In my Kotlin/Java file, when I replace

val encodedQueryParams = URLEncoder.encode(queryParams, Charsets.UTF_8.toString())

By

val encodedQueryParams = "pathURI=http%3A%2F%2Fmy.domain.net%2F%2A&expiry=1553937508&reuse=0"

Then my rest code will generate a token which is exactly as same as what Python generates. Therefore, it indicates that something is wrong with my URLEncoder.encode.

Hesam
  • 52,260
  • 74
  • 224
  • 365

1 Answers1

0

Thanks to @user207421. I found what was my mistake and how should I fix it. So, this is the equivalent Kotlin code:

fun main(args: Array<String>) {
    val requestParams = HashMap<String, String>()
    requestParams["pathURI"] = PATH_URI
    requestParams["expiry"] = expiryTime(10)
    requestParams["reuse"] = REUSE.toString()

    val encodedQueryParams = requestParams.keys.stream()
        .map { key -> "$key=${encodeValue(requestParams[key].orEmpty())}" }
        .reduce { p1: String?, p2: String? -> "$p1&$p2" }
        .map { s -> "?$s" }
        .orElse("")
    println(encodedQueryParams)

    // ... rest of my code
}

fun encodeValue(value: String): String {
    return URLEncoder.encode(value, Charsets.UTF_8.toString())
}

The gist can be found here.

Hesam
  • 52,260
  • 74
  • 224
  • 365
  • You also need to encode the keys if there is any risk they may contain encode-worthy characters. – user207421 Mar 30 '19 at 01:13
  • Thanks, @user207421 for your review. Backend is looking for these keys in order to extract their values. So, that's why I didn't encode them. But, it worth trying. I'll do that. Thanks again. – Hesam Mar 30 '19 at 19:12