Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

WMS Authorization header #13835

Closed
Nxele opened this issue Jan 30, 2019 · 8 comments
Closed

WMS Authorization header #13835

Nxele opened this issue Jan 30, 2019 · 8 comments

Comments

@Nxele
Copy link

Nxele commented Jan 30, 2019

Greeting
we have a satellite image service provider called Airbus. we want to make a call to their WMS restful API using mapBox Android SDK. the issue is Airbus requires us to pass a Authorization header with the key (token) when making the call for security seasons. and on mapBox SDK you can only pass the url source as a string and not the header.

please not we can make calls to other WMS services that doesn't require Authorization header

Steps to reproduce

  1. Add a feature to allow us to pass the Authorization header with the url_source or just the url for WMS services that doesn't require Authorization header we must have both the options.

Expected behavior

When passing the url_source and the Authorization header with the key or token the mapBox SDK should render the image on the device.

Actual behavior

I don't get the Satellite image i get the error below

/Mbgl: {GLThread 1090}[Style]: Failed to load tile 9/296/293=>9 for source web-map-source: HTTP status code 401 (401 Authorization error code)

Configuration

Android versions: 8.1
Device models:Emulator Nexus 4
Mapbox SDK versions:6.8.1

Please note I'm using Mapbox SDK version 6.8.1 because 7.0.1 wouldn't allow me to use these methods addSource() and addLayerBelow(). but worked on 6.8.1
airbis-wms

@tobrun
Copy link
Member

tobrun commented Jan 30, 2019

Please note I'm using Mapbox SDK version 6.8.1 because 7.0.1 wouldn't allow me to use these methods addSource() and addLayerBelow(). but worked on 6.8.1

With 7.0.0, we refactored how OnMapReady invocation and style loading is performed. You need to update your code to match this paradigm. Here is a simple example, you can provide a callback to that method so you have access to Style.java. This will allow you add sources and layers.

the issue is Airbus requires us to pass a Authorization header with the key (token) when making the call for security seasons.

This is not a feature directly exposed by the SDK but you can add this integration by using an own HttpClient. You can do this by using: HttpRequestUtil#setOkHttpClient and add some interceptors to modify the headers.

Closing as answered.

@tobrun tobrun closed this as completed Jan 30, 2019
@Nxele
Copy link
Author

Nxele commented Jan 30, 2019

Ok Thanks Tobrun will give it a try so you mean some of the code on examples might not work on new SDK version

can you please clarify here i only have 1 week working with mapBox
This is not a feature directly exposed by the SDK but you can add this integration by using an own HttpClient. You can do this by using: HttpRequestUtil#setOkHttpClient and add some interceptors to modify the headers

@tobrun
Copy link
Member

tobrun commented Jan 30, 2019

Here is a migration guide @Nxele: https://github.com/mapbox/mapbox-gl-native/wiki/Android-6.x-to-7.x-migration-guide

This is not a feature directly exposed by the SDK but you can add this integration by using an own HttpClient. You can do this by using: HttpRequestUtil#setOkHttpClient and add some interceptors to modify the headers

The Android SDK in this repository uses OkHttp as HttpClient (which is the default for Android development). That library exposes a configuration for you to intercept http requests and change things to them, eg add a header. THe SDK in this repository exposes a way for you to define your own OkHttpClient and thus allow for using these interceptors. https://stackoverflow.com/questions/32196424/how-to-add-headers-to-okhttp-request-interceptor

@Nxele
Copy link
Author

Nxele commented Jan 31, 2019

Hi Tobrun

Just for clarity

I've locked at these classes just wanna make sure if this is exactly what you are talking about

I've tried this extending HttpRequest and made these changes Request.Builder builder = new Request.Builder().addHeader("Authorization",Airbus_key); but on the main call it's declared as final

link to the classes

https://github.com/mapbox/mapbox-gl-native/pull/12449/files#diff-70a86c6769ec7890977716965f5734b7
git-hub

@tobrun
Copy link
Member

tobrun commented Jan 31, 2019

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
    httpClient.addInterceptor(chain -> {
      Request original = chain.request();

      Request request = original.newBuilder()
        .header("Header-Name", "Your-Value")
        .method(original.method(), original.body())
        .build();

      return chain.proceed(request);
    };
    HttpRequestUtil.setOkHttpClient(httpClient.build());
    
    setContentView(R.layout.activity_map_simple);
    mapView = findViewById(R.id.mapView);
    mapView.onCreate(savedInstanceState);
    mapView.getMapAsync(mapboxMap -> mapboxMap.setStyle(
      new Style.Builder().fromUrl(Style.MAPBOX_STREETS)
    ));
  }

@Nxele
Copy link
Author

Nxele commented Jan 31, 2019

Thanks tobrun

i was struggling with making this call HttpRequestUtil.setOkHttpClient(httpClient.build());

i was using one of the code you gave me

OkHttpClient.Builder httpClient = new OkHttpClient.Builder();

    httpClient.addInterceptor(new Interceptor() {

          @Override
          public Response intercept(Interceptor.Chain chain) throws IOException {
              Request original = chain.request();

              Request request = original.newBuilder()
                      //.header("User-Agent", "Your-App-Name")
                      .addHeader("Authorization", Airbus_key)
                      .method(original.method(), original.body())
                      .build();

              return chain.proceed(request);
          }
      });

    OkHttpClient client = httpClient.build();

    Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://view.geoapi-airbusds.com")
    .addConverterFactory(GsonConverterFactory.create())
    .client(client)
    .build();

is there a huge difference but i like the one you've sent just now less code ?

I'm getting this error now

2019-01-31 16:17:34.682 14787-14831/com.maps.airbusmapbox V/Mbgl-HttpRequest: [HTTP] Request was successful (code = 200).
2019-01-31 16:17:34.693 14787-14816/com.maps.airbusmapbox D/skia: --- SkAndroidCodec::NewFromStream returned null
2019-01-31 16:17:34.695 14787-14820/com.maps.airbusmapbox E/Mbgl: {GLThread 1543}[Style]: Failed to load tile 9/295/293=>9 for source web-map-source: bitmap decoding: couldn't get bitmap info
2019-01-31 16:17:34.716 14787-14849/com.maps.airbusmapbox V/Mbgl-HttpRequest: [HTTP] Request was successful (code = 200).
2019-01-31 16:17:34.727 14787-14815/com.maps.airbusmapbox D/skia: --- SkAndroidCodec::NewFromStream returned null
2019-01-31 16:17:34.728 14787-14820/com.maps.airbusmapbox E/Mbgl: {GLThread 1543}[Style]: Failed to load tile 3/4/4=>3 for source web-map-source: bitmap decoding: couldn't get bitmap info
2019-01-31 16:17:34.815 14787-14833/com.maps.airbusmapbox V/Mbgl-HttpRequest: [HTTP] Request was successful (code = 200).
2019-01-31 16:17:34.837 14787-14818/com.maps.airbusmapbox D/skia: --- SkAndroidCodec::NewFromStream returned null
2019-01-31 16:17:34.840 14787-14820/com.maps.airbusmapbox E/Mbgl: {GLThread 1543}[Style]: Failed to load tile 2/2/2=>2 for source web-map-source: bitmap decoding: couldn't get bitmap info
2019-01-31 16:17:34.902 14787-14836/com.maps.airbusmapbox V/Mbgl-HttpRequest: [HTTP] Request was successful (code = 200).
2019-01-31 16:17:34.907 14787-14837/com.maps.airbusmapbox V/Mbgl-HttpRequest: [HTTP] Request was successful (code = 200).
2019-01-31 16:17:34.927 14787-14817/com.maps.airbusmapbox D/skia: --- SkAndroidCodec::NewFromStream returned null
2019-01-31 16:17:34.928 14787-14820/com.maps.airbusmapbox E/Mbgl: {GLThread 1543}[Style]: Failed to load tile 1/1/1=>1 for source web-map-source: bitmap decoding: couldn't get bitmap info
2019-01-31 16:17:34.941 14787-14816/com.maps.airbusmapbox D/skia: --- SkAndroidCodec::NewFromStream returned null
2019-01-31 16:17:34.943 14787-14820/com.maps.airbusmapbox E/Mbgl: {GLThread 1543}[Style]: Failed to load tile 0/0/0=>0 for source web-map-source: bitmap decoding: couldn't get bitmap info

This is how i'm callling the WMS image
String airBus_source = "https://view.geoapi-airbusds.com/api/v1/map/imagery.wms?version=1.1.1&request=GetMap&service=WMS&WIDTH=256&HEIGHT=256&FORMAT=image/png&EPSG:3857&bbox={bbox-epsg-3857}";

                    RasterSource airbus_image = new RasterSource("web-map-source",new TileSet("tileset",airBus_source),256);
                    style.addSource(airbus_image);

                    RasterLayer webMapLayer = new RasterLayer("web-map-layer", "web-map-source");
                    style.addLayerBelow(webMapLayer, "aeroway-taxiway");

@Nxele
Copy link
Author

Nxele commented Jan 31, 2019

To me it look like the request went through but now it's failing to load the images

@Nxele
Copy link
Author

Nxele commented Feb 7, 2019

Thanks a lot Tobrun you are a Code Hero your help was highly appreciated everything works like charm ever since you gave me that code.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants