2013-08-28 29 views
62

Tôi đang sử dụng OAuth và tôi cần đặt mã thông báo OAuth vào tiêu đề của mình mỗi lần tôi thực hiện yêu cầu. Tôi thấy chú thích @Header, nhưng có cách nào để làm cho nó được tham số hóa để tôi có thể truyền vào lúc chạy không?Android Retrofit Parameterized @Headers

Dưới đây là khái niệm

@Header({Authorization:'OAuth {var}', api_version={var} })

Bạn có thể vượt qua họ trong lúc Runtime?

@GET("/users") 
void getUsers(
    @Header("Authorization") String auth, 
    @Header("X-Api-Version") String version, 
    Callback<User> callback 
) 
+0

Bạn đã bao giờ tìm ra điều này chưa? Tôi cần phải nhập một mã thông báo trong tiêu đề cũng – theSociableme

+0

Tôi cũng đang tìm kiếm giải pháp cho điều này, từ tài liệu có vẻ như [@Headers()] (http://square.github.io/retrofit/javadoc/retrofit/ http/Header.html) chú thích trên phương thức _adds fields_ để tiêu đề từng cái một, nhưng chỉ hỗ trợ chữ. Và [@Header ("tham số") Chuỗi chuỗi] (http://square.github.io/retrofit/javadoc/retrofit/http/Header.html) tham số chú thích _replaces_ tiêu đề với giá trị được cung cấp. – nana

+1

Tương tự ở đây, không thể tìm hiểu cách xử lý các phiên khi sử dụng trang bị thêm. – feresr

Trả lời

89

Ngoài việc sử dụng @Header tham số, tôi muốn sử dụng RequestInterceptor để cập nhật tất cả các yêu cầu của bạn mà không thay đổi giao diện của bạn. Sử dụng một cái gì đó như:

RestAdapter.Builder builder = new RestAdapter.Builder() 
    .setRequestInterceptor(new RequestInterceptor() { 
     @Override 
     public void intercept(RequestFacade request) { 
      request.addHeader("Accept", "application/json;versions=1"); 
      if (isUserLoggedIn()) { 
       request.addHeader("Authorization", getToken()); 
      }      
     } 
    }); 

p/s: Nếu bạn đang sử dụng Retrofit2, bạn nên chú ý Interceptor thay vì RequestInterceptor

Kể từ RequestInterceptor là không còn có sẵn trong Retrofit 2.0

+3

Điều này không liên quan trực tiếp nhưng nếu bạn thấy mình cần lấy giá trị từ đối tượng yêu cầu để tạo tiêu đề Cấp phép, bạn cần mở rộng ApacheClient và thực thi trùng lặp đối tượng Yêu cầu (Danh sách

tiêu đề = ...; Yêu cầu requestNew = new Request (request.getMethod(), request.getUrl(), tiêu đề, request.getBody()); request = requestNew). –

+1

Đó là một thủ thuật làm rối loạn mã hóa, sử dụng tốt hơn câu trả lời của @ nana –

+0

'RestAdapter' phụ thuộc vào Retrofit1, trong Retrofit2 nó là' Retrofit'. Im sẽ sử dụng Retrofit2, vì vậy nó không có vấn đề nếu sử dụng 'RequestInterceptor' như mã trên? –

45

Có, bạn có thể chuyển chúng trong thời gian chạy. Như một vấn đề của thực tế, khá nhiều chính xác như bạn gõ nó ra. Đây sẽ là trong lớp giao diện API của bạn, tên nói SecretApiInterface.java

public interface SecretApiInterface { 

    @GET("/secret_things") 
    SecretThing.List getSecretThings(@Header("Authorization") String token) 

} 

Sau đó, bạn vượt qua các thông số để giao diện này từ yêu cầu của bạn, một cái gì đó dọc theo những đường: (tập tin này sẽ là ví dụ SecretThingRequest. java)

public class SecretThingRequest extends RetrofitSpiceRequest<SecretThing.List, SecretApiInteface>{ 

    private String token; 

    public SecretThingRequest(String token) { 
     super(SecretThing.List.class, SecretApiInterface.class); 
     this.token = token; 
    } 

    @Override 
    public SecretThing.List loadDataFromNetwork() { 
     SecretApiInterface service = getService(); 
     return service.getSecretThings(Somehow.Magically.getToken()); 
    } 
} 

đâu Somehow.Magically.getToken() là một lời gọi phương thức trả về một mã thông báo, đó là tùy thuộc vào bạn ở đâu và làm thế nào bạn định nghĩa nó.

Bạn có thể có nhiều hơn một @Header("Blah") String blah chú thích trong việc triển khai giao diện, như trong trường hợp của bạn!

tôi thấy nó khó hiểu quá, the documentation nói rõ nó thay thế tiêu đề, nhưng nó KHÔNG!
Nó được trong thực tế bổ sung như với @Headers("hardcoded_string_of_liited_use") chú thích

Hope this helps;)

+0

Tôi tìm thấy trong tài liệu rằng nó không thay thế tiêu đề hiện tại: "Lưu ý rằng tiêu đề không ghi đè lên nhau." Kiểm tra http://square.github.io/retrofit/ và "Header Manipulation" – zatziky

+0

Đó là tin tốt, nó phải có bản sửa lỗi rồi! – nana

27

Câu trả lời được chấp nhận là cho phiên bản cũ của Retrofit. Đối với người xem trong tương lai, cách thực hiện điều này với Retrofit 2.0 đang sử dụng ứng dụng khách OkHttp tùy chỉnh:

OkHttpClient httpClient = new OkHttpClient.Builder() 
    .addInterceptor(new Interceptor() { 
    @Override 
    public Response intercept(Chain chain) throws IOException { 
     Builder ongoing = chain.request().newBuilder(); 
     ongoing.addHeader("Accept", "application/json;versions=1"); 
     if (isUserLoggedIn()) { 
     ongoing.addHeader("Authorization", getToken()); 
     } 
     return chain.proceed(ongoing.build()); 
    } 
    }) 
    .build(); 

Retrofit retrofit = new Retrofit.Builder() 
    // ... extra config 
    .client(httpClient) 
    .build(); 

Hy vọng nó sẽ giúp ai đó. :)

+3

Trong sử dụng phổ biến với dagger2, retrofit2 sẽ là singleton, do đó httpclient sẽ không được tạo ra mỗi lần. trong trường hợp đó isUserLoggedIn() không có ý nghĩa, tôi có đúng không? Chỉ có giải pháp tôi có thể thấy hiện nay là buộc retrofit2 reinitialization khi trạng thái đăng nhập của người dùng được thay đổi, để tiêu đề thích hợp được thêm vào hoặc bị xóa khỏi yêu cầu .. hoặc có một số giải pháp rõ ràng mà tôi không thể thấy hiện tại? Cảm ơn. – bajicdusko

+0

@bajicdusko đây chính là câu chuyện giống hệt nhau của tôi. Bạn đã tìm thấy giải pháp chưa? Có vẻ như lãng phí, và kỳ lạ là phiên bản trước đó hiệu quả hơn. – deed02392

+0

@ deed02392 Bạn có thể đặt bộ tổng hợp 'Bộ chặn 'mà bạn có thể đặt hoặc đặt lại bộ chặn trong giai đoạn sau. Tuy nhiên, tôi cho rằng việc trang bị thêm như một singleton có thể là dấu hiệu của việc tối ưu hóa sớm. Không có phí khi tạo một phiên bản trang bị mới: https://github.com/square/retrofit/blob/master/retrofit/src/main/java/retrofit2/Retrofit.java – pablisco

Các vấn đề liên quan