1

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.

2
  • You're doing it wrong in Java. You need to encode the query parameter names and values individually. Commented Mar 30, 2019 at 0:32
  • @user207421 You are absolutely right. Thanks for your guide. Commented Mar 30, 2019 at 1:03

1 Answer 1

1

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=${requestParams[key].orEmpty().encode()}" }
        .reduce { p1: String?, p2: String? -> "$p1&$p2" }
        .map { s -> "?$s" }
        .orElse("")
    println(encodedQueryParams)

    // ... rest of my code
}

fun String.encode() = URLEncoder.encode(this, Charsets.UTF_8)

The gist can be found here.

Sign up to request clarification or add additional context in comments.

2 Comments

You also need to encode the keys if there is any risk they may contain encode-worthy characters.
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.