I tried use ktor-client to do a put request, uploa...
# android
i
I tried use ktor-client to do a put request, upload some files into web, but that give me a redirect unhandle exception, please help, https://paste.ubuntu.com/p/5mFhHRCZHp/
g
It’s not allowed by default to redirect for POST/PUT, for security reasons only GET request will redirect
you can disable it on request level if you want:
Copy code
install(HttpRedirect) {
   checkHttpMethod = false
}
There are other problems in your code though, you block suspend functions with your write/read output stream, use suspend versions of it which provided by Ktor
you correctly wrap them to IO on top level, but better do this on level of function which doing blocking operations
i
if I disable http redirect, get request won't do redirect too? there're download and upload two function, an they're both redirected
g
Snippet which I sent doesn’t disable http redirect, it disable HTTP Method validation for redirects, only GET and HEAD methods allowed to redirect by default, but you can disable it and follow redirect for other http methods
but in general, better to just avoid redirect and PUT to final URL if it possible
i
g
Copy code
No transformation found: class io.ktor.utils.io.ByteBufferChannel
it’s completely different error
i
oh, my mistake
g
You cannot just request headers
but you can receive whole response and get headers from it
followRedirects = false
In second one you just completely disabled redirects, so it’s kinda expected that it fails on redirect
i
you're right
Copy code
val output = client.put<HttpResponse>(addr)
        println("this is upload test ${output.headers}")
// I get this headers now
now I get the final url to put, how I can use ktor put outputStream to that url?
there's too less message about http requests on https://ktor.io/docs/request.html#customizing-requests
Copy code
val output = client.put<HttpResponse>(addr)
        println("this is upload test ${output.headers["Location"]}")
        val realUrl = output.headers["Location"]?:""
        val result = client.put<OutputStream>(realUrl)
        result.write("abc".toByteArray())
        result.flush()
io.ktor.client.call.NoTransformationFoundException: No transformation found: class io.ktor.utils.io.ByteBufferChannel (Kotlin reflection is not available) -> class
g
It’s quick start page, you can find more docs in specific parts of the doc
So what is “> class”?
OutputStream?
it’s apparently not available
i
io.ktor.client.call.NoTransformationFoundException: No transformation found: class io.ktor.utils.io.ByteBufferChannel (Kotlin reflection is not available) -> class java.io.OutputStream (Kotlin reflection is not available)
g
you can receive HttpResponse though
and get output stream from it
Please check doc, there are examples how to use it https://ktor.io/docs/requests.html#post-put-and-patch
i
Copy code
val output = client.put<HttpResponse>(addr)
        println("this is upload test ${output.headers["Location"]}")
        val realUrl = output.headers["Location"]?:""
        val result = client.put<HttpResponse>(realUrl)
        val r1 = result.receive<OutputStream>()
        r1.write("abc".toByteArray())
        r1.flush()
g
do you understand what this error message mean?
it just says that there is no way to get OutputStream directly from request, and what is the reason for this? you cannot write anything there anyway
you probably want to write to request, not receive it
please, check docs first
i
sorry, I'll do it
I still don't know how to write to request...
g
You can ask for help in #ktor channel if you explain your case and what you are trying to do
i
problem solved
Copy code
client.put<ByteArray>(realUrl){
            body = "aha".toByteArray()
        }
I just copycat that POST usage and use it for PUT, and it just worked!
g
well yeah, this doc about Ktor server, not ktor client, sorry for confusion
It also mentioned in client doc about request itself: https://ktor.io/docs/request.html#specifying-a-body-for-requests
Also you original issue mentioned here: https://ktor.io/docs/response-validation.html#expect-success but way to fix it a bit different, just disable whole feature, not only disable it on request level
i
aha, thanks