2015-10-01 70 views
1

朋友!Android上NanoHTTPD的意外HTTP 400狀態碼

我在我的Android應用程序中收到來自nanohttpd的偶然和意外的HTTP 400響應。錯誤遵循特定模式。我已經看了一段時間了,但我已經到了需要不同角度或其他幫助指向正確方向的地步。

您能否看看並分享您的想法,甚至直接提出意見和建議?

  • 爲什麼我得到這個HTTP 400狀態碼?
  • 爲什麼只有在給定的情況下? (我不希望它在所有!)

一些背景

我在我的Android項目運行nanohttpd作爲臨時隔離層(由於服務器端的不是成熟,還不足以) 。我在Android Service中隔離了nanohttpd服務器,該服務器在創建後從我的自定義Application對象開始。這種方式nanohttpd不綁定到任何特定的生命週期,但可以獨立於整個應用程序邏輯和組件生命週期而生活。

的問題

現在,(幾乎)一切工作很好,很正常,我可以開始nanohttpd並執行一些初始的登錄請求,我希望模擬響應甚至交付。當我執行我的第一個「GET」請求時,儘管如此,nanohttpd會向我發出400個錯誤的請求狀態,但只有第一次。如果我退出負責特定「GET」請求的Activity,並再次(從主屏幕)啓動它,它將以200狀態完美地提供預期的有效負載。

我做了這麼遠

我曾在nanohttpd源代碼,仔細一看,試圖追查地方,爲什麼這400個狀態設置。這種狀態碼的使用並不是很多地方。粗略地說只有here,herehere。由於我沒有處理多部分內容,因此我只剩下第一個和第三個「在這裏」。但是 - 當然 - 我不能在我的生活中找到400身份的根本原因,也不能確定哪個確切的區塊會爲我造成這種狀態。當我調試代碼時,一切都正常工作。

一些代碼

這大致就是我nanohttpdServiceMyNanoHttpdService)看起來像:

@Override 
public int onStartCommand(Intent intent, int flags, int startId) { 
    if (ACTION_START.equals(intent.getAction())) { 
     String errorMessage = null; 

     if (myNanoHttpd == null) { 
      String hostUrl = intent.getStringExtra(EXTRA_HOST); 
      Uri uri = Utils.notEmpty(hostUrl) ? Uri.parse(hostUrl) : Uri.EMPTY; 
      myNanoHttpd = new MyNanoHttpd(this, uri.getHost(), uri.getPort(), null); 
     } 

     if (!myNanoHttpd.isAlive()) { 
      try { 
       myNanoHttpd.start(); 
      } catch (IOException e) { 
       StringWriter stringWriter = new StringWriter(); 
       PrintWriter printWriter = new PrintWriter(stringWriter); 
       e.printStackTrace(printWriter); 
       errorMessage = stringWriter.toString(); 
       stopSelf(); 
      } 
     } 

     final ResultReceiver resultReceiver = intent.getParcelableExtra(EXTRA_RESULT_LISTENER); 
     if (resultReceiver != null) { 
      int status = myNanoHttpd.isAlive() ? CODE_SUCCESS : CODE_FAILURE; 
      Bundle bundle = new Bundle(); 
      bundle.putString(EXTRA_MESSAGE, errorMessage); 
      resultReceiver.send(status, bundle); 
     } 
    } 

    return Service.START_STICKY; 
} 

這是我開始從我的自定義Application對象的服務,初始化我的客戶端狀態並獲取一些內容:

@Override 
public void onCreate() { 
    super.onCreate(); 

    // Yes, that is a Java 8 Lambda you see there! 
    MyNanoHttpdService 
      .start(this, "http://localhost:8080") 
      .withStartupListener((status, message) -> { 
       if (status == 0) { 
        // POST REQUEST: Works like a charm 
        myNetworkHelper.login(); 

        // GET REQUEST: Always fails on first launch 
        myNetworkHelper.getContent(); 
       } else { 
        Log.e("LOG_TAG", "Couldn't start MyNanoHttpd: " + message); 
       } 
      }); 
} 

假設包裝便利代碼(.withStartupListener(...) - 基本上包裝Service所使用的ResultReceiver - 和myNetworkHelper對象)按預期工作是安全的。此外,在製作中,getContent()電話將由ActivityFragment撥打,但爲了方便起見,我現在已將其撥至Application

回答

1

我可能找到了我的問題的根源,甚至可能是目前的解決方法。

如果我在我的調查中是正確的,則問題是由於以前(POST)請求中未使用的數據造成的,污染了當前(POST)請求。

This線在NanoHTTPD代碼庫(標題在NanoHTTPD.HTTPSession.execute()方法解析塊,只調用通過任何自定義serve(...)方法之前 - 第三「這裏」在我的上述問題)是非常線,其中HTTP 400狀態代碼被拋出,正如代碼所示,對於"method"頭文件沒有適當的值。

值 - 我希望以明文形式顯示爲「POST」 - 已被前一個請求的JSON內容主體部分所污染。當我意識到這一點,我試圖消耗整個請求主體在我的自定義MyNanoHttpd.serve(IHTTPSession session)方法,像這樣:

@Override 
public Response serve(IHTTPSesion session) { 
    InputStream inputStream = session.getInputStream(); 
    inputStream.skip(inputStream.available()); 

    // or 
    // inputStream.skip(Long.MAX_VALUE); 

    // or even 
    // inputStream.close(); 

    ... 

} 

這沒有工作,雖然,因爲我一直得到各種異常。我最終輕輕修改了NanoHTTPD代碼,而是安全地關閉了方法的finally塊中的輸入流。

但是,我正在考慮與NanoHTTPD社區接觸,討論合適的可持續解決方案。