-
-
Save swankjesse/8571a8207a5815cca1fb to your computer and use it in GitHub Desktop.
import java.io.IOException; | |
import okhttp3.HttpUrl; | |
import okhttp3.Interceptor; | |
import okhttp3.OkHttpClient; | |
import okhttp3.Request; | |
/** An interceptor that allows runtime changes to the URL hostname. */ | |
public final class HostSelectionInterceptor implements Interceptor { | |
private volatile String host; | |
public void setHost(String host) { | |
this.host = host; | |
} | |
@Override public okhttp3.Response intercept(Chain chain) throws IOException { | |
Request request = chain.request(); | |
String host = this.host; | |
if (host != null) { | |
HttpUrl newUrl = request.url().newBuilder() | |
.host(host) | |
.build(); | |
request = request.newBuilder() | |
.url(newUrl) | |
.build(); | |
} | |
return chain.proceed(request); | |
} | |
public static void main(String[] args) throws Exception { | |
HostSelectionInterceptor interceptor = new HostSelectionInterceptor(); | |
OkHttpClient okHttpClient = new OkHttpClient.Builder() | |
.addInterceptor(interceptor) | |
.build(); | |
Request request = new Request.Builder() | |
.url("http://www.coca-cola.com/robots.txt") | |
.build(); | |
okhttp3.Call call1 = okHttpClient.newCall(request); | |
okhttp3.Response response1 = call1.execute(); | |
System.out.println("RESPONSE FROM: " + response1.request().url()); | |
System.out.println(response1.body().string()); | |
interceptor.setHost("www.pepsi.com"); | |
okhttp3.Call call2 = okHttpClient.newCall(request); | |
okhttp3.Response response2 = call2.execute(); | |
System.out.println("RESPONSE FROM: " + response2.request().url()); | |
System.out.println(response2.body().string()); | |
} | |
} |
Has something changed with the okhttp3 API? When I try to change the host I get this:
network interceptor must retain the same host and port
My guess is that this has to be used with addInterceptor
rather than addNetworkInterceptor
. As @joshafeinberg points out, if you try to change the host or port with an Interceptor added via addNetworkInterceptor
, you get an error (with okhttp3 at least). I've had success altering those fields with addInterceptor
, though.
How this work with retrofit2? Seems like its just replaces whole request url
This seems to be working for me.
Thanks!
class ChangeableBaseUrlInterceptor : Interceptor {
@Volatile private var host: HttpUrl? = null
fun setHost(url: String) {
this.host = HttpUrl.parse(url)
}
@Throws(IOException::class)
override fun intercept(chain: Interceptor.Chain): Response {
val newRequest = host?.let {
val newUrl = chain.request().url().newBuilder()
.scheme(it.scheme())
.host(it.url().toURI().host)
.port(it.port())
.build()
return@let chain.request().newBuilder()
.url(newUrl)
.build()
}
return chain.proceed(newRequest)
}
}
This solution will affect @get (full path) @post (full path) and @url so that they can not work,try my solution: https://github.com/JessYanCoding/RetrofitUrlManager
@JessYanCoding was using this class until I ran into same issue you mentioned. My @url's base url got replaced with intercepted host. Thanks for creating your library.
@JessYanCoding Could you elaborate on why this solution won't work? The whole objective is to intercept the request and change the host alone to whatever we want. So how is this affecting @get(full path) ?
@thsaravana You try, @get(full path) will be replaced with intercepted host
@JessYanCoding
I request two api with different baseUrl at the same time, one of the request's baseUrl is wrong.
mHost.setHost(Urls.DOUBAN_FILM_URL_HOST)
mRetrofit.create(FilmsApi::class.java)
.getInTheaters()
.flatMap { filmsData -> Observable.fromIterable(filmsData.films) }
.compose(TransformScheduler.applyNewThreadScheduler())
.subscribe(
{ film ->
val filmEntity = FilmEntity(text = film.title, comment = film.originalTitle, date = Date())
Log.e("TAG", "put success " + filmEntity.text)
},
{ e ->
Log.e("TAG", e.message)
})
mHost.setHost(Urls.GANK_GIRLS_URL_HOST)
mRetrofit.create(GirlsApi::class.java)
.accessGirls(1)
.compose(TransformScheduler.applyNewThreadScheduler())
.subscribe({ girl ->
Log.e("TAG", "size " + girl.results.size)
})
The two baseurl are: http://gank.io/
and https://api.douban.com/
And occur this:
D/OkHttp: <-- 404 Not Found http://gank.io/v2/movie/in_theaters (308ms)
This is wrong because the base url is https://api.douban.com/
but not http://gank.io/
I think it course by concurrency with the Volatile
, how solve it?
@iBotasky Because the network request is asynchronous, try https://github.com/JessYanCoding/RetrofitUrlManager
I have a good implementation plan, which will be easier to use and solve the problem more thoroughly. Welcome everyone to try https://github.com/uni-cstar/oknet
It did not like ASP.NET web application URLs such as http://domain.com/MyWebApp, so I had to change setHost slightly:
public void setHost(String host) { // Store the actual host as "domain.com" this.host = HttpUrl.parse(host).host(); }