Skip to content
This repository has been archived by the owner on Jul 24, 2022. It is now read-only.

Commit

Permalink
Proxy audio to avoid IP restriction. Fixes #28
Browse files Browse the repository at this point in the history
  • Loading branch information
meoyawn committed Dec 23, 2018
1 parent a1fd354 commit 257bc25
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 33 deletions.
4 changes: 1 addition & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,9 @@ dependencies {
compile "com.google.apis:google-api-services-youtube:v3-rev205-1.25.0"
compile "com.google.api-client:google-api-client-jackson2:1.25.0"

compile "io.ktor:ktor-client-core:$ktor_version"
compile "io.ktor:ktor-client-jetty:$ktor_version"
compile "io.ktor:ktor-server-netty:$ktor_version"
compile "io.ktor:ktor-html-builder:$ktor_version"
compile "io.ktor:ktor-client-cio:$ktor_version"
compile "io.ktor:ktor-client-apache:$ktor_version"

compile "com.yandex.android:disk-restapi-sdk:1.03"

Expand Down
59 changes: 29 additions & 30 deletions src/main/kotlin/adeln/main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import io.ktor.application.call
import io.ktor.application.install
import io.ktor.client.HttpClient
import io.ktor.client.call.call
import io.ktor.client.engine.cio.CIO
import io.ktor.client.engine.apache.Apache
import io.ktor.features.AutoHeadResponse
import io.ktor.features.Compression
import io.ktor.html.respondHtml
Expand All @@ -24,6 +24,7 @@ import io.ktor.routing.route
import io.ktor.routing.routing
import io.ktor.server.engine.embeddedServer
import io.ktor.server.netty.Netty
import io.ktor.util.StringValues
import io.ktor.util.filter
import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.io.ByteWriteChannel
Expand Down Expand Up @@ -68,13 +69,13 @@ fun mkClient(): OkHttpClient =

val BLOCKING_IO = Executors.newCachedThreadPool().asCoroutineDispatcher()

@io.ktor.util.KtorExperimentalAPI
fun main(args: Array<String>) {

val client = mkClient()
val youtube = mkYoutube()
val output = SyndFeedOutput()
val yandexDisk = mkYandexDisk()
val ktorClient = HttpClient(Apache)

embeddedServer(Netty, port = Config.PORT) {

Expand Down Expand Up @@ -137,7 +138,7 @@ fun main(args: Array<String>) {

println("got audio $audio")

call.proxyYoutubeRequest(audio.url.toString())
call.proxy(ktorClient, audio.url)
}

route("/yandexdisk") {
Expand All @@ -164,38 +165,36 @@ fun ApplicationRequest.isBrowser(): Boolean =
fun ApplicationRequest.player(): Player =
if (isBrowser()) Player.BROWSER else Player.OTHER

@io.ktor.util.KtorExperimentalAPI
suspend fun ApplicationCall.proxyYoutubeRequest(url: String) {
fun Headers.without(headers: Set<String>): StringValues =
filter { key, _ -> headers.all { !it.equals(key, ignoreCase = true) } }

try{
suspend fun ApplicationCall.proxy(client: HttpClient, url: HttpUrl) {

val httpClient = HttpClient(CIO)
val originalHeaders = request.headers
val result = client.call(url.toString()) {
headers.appendAll(originalHeaders.without(setOf(HttpHeaders.Host)))
}

// We create a GET request to the wikipedia domain and return the call (with the request and the unprocessed response).
val result = httpClient.call(url)
val proxiedHeaders = result.response.headers
val contentType = proxiedHeaders[HttpHeaders.ContentType]
val contentLength = proxiedHeaders[HttpHeaders.ContentLength]

// Get the relevant headers of the client response.
val proxiedHeaders = result.response.headers
val contentType = proxiedHeaders[HttpHeaders.ContentType]
val contentLength = proxiedHeaders[HttpHeaders.ContentLength]
respond(object : OutgoingContent.WriteChannelContent() {

// We simply pipe it. We return a [OutgoingContent.WriteChannelContent]
// propagating the contentLength, the contentType and other headers, and simply we copy
// the ByteReadChannel from the HTTP client response, to the HTTP server ByteWriteChannel response.
respond(object : OutgoingContent.WriteChannelContent() {
override val contentLength: Long? = contentLength?.toLong()
override val contentType: ContentType? = contentType?.let { ContentType.parse(it) }
override val headers: Headers = Headers.build {
appendAll(proxiedHeaders.filter { key, _ -> !key.equals(HttpHeaders.ContentType, ignoreCase = true) && !key.equals(HttpHeaders.ContentLength, ignoreCase = true) })
}
override val status: HttpStatusCode? = result.response.status
override suspend fun writeTo(channel: ByteWriteChannel) {
result.response.content.copyAndClose(channel)
}
})
} catch (e: Exception) {
println(e)
}
override val contentLength: Long? = contentLength?.toLong()

override val contentType: ContentType? = contentType?.let { ContentType.parse(it) }

override val headers: Headers = Headers.build {
appendAll(proxiedHeaders.without(setOf(HttpHeaders.ContentType, HttpHeaders.ContentLength)))
}

override val status: HttpStatusCode? = result.response.status

override suspend fun writeTo(channel: ByteWriteChannel) {
result.response.content.copyAndClose(channel)
}
})
}

private fun HTML.renderHome(url: String?, resolved: HttpUrl?) {
Expand Down

0 comments on commit 257bc25

Please sign in to comment.