2016-04-12 8 views
4

Ich entwickle gerade eine Website mit Phoenix und habe einen Videobereich, der im Hintergrund spielen soll.HTTP-Bereichsanfrage mit Phoenix?

Obwohl es auf Chrome & Firefox funktioniert, funktioniert es nicht auf Safari.

Ich vermute, es ist, weil Cowboy HTTP Range Request nicht korrekt bedient.

Gibt es eine Möglichkeit zu aktivieren (wenn standardmäßig deaktiviert)?

$ curl -H Range:bytes=16- -I http://localhost:4000/videos/vid_home_1.mp4 
HTTP/1.1 200 OK 
server: Cowboy 
date: Tue, 12 Apr 2016 14:41:20 GMT 
content-length: 633787 
cache-control: public 
etag: 480A03F 
content-type: video/mp4 

Wann sollte es eine 206 sein, wie mit einem nginx-Server angezeigt:

$ curl -H Range:bytes=16- -I http://localhost/videos/vid_home_1.mp4 
HTTP/1.1 206 Partial Content 
Server: nginx/1.8.0 
Date: Tue, 12 Apr 2016 14:46:17 GMT 
Content-Type: video/mp4 
Content-Length: 633771 
Last-Modified: Mon, 11 Apr 2016 12:26:26 GMT 
Connection: keep-alive 
ETag: "570b97f2-9abbb" 
Content-Range: bytes 16-633786/633787 
+0

warum dienen statische Inhalte durch Cowboy? – ardhitama

+0

@ardhitama: Naja, hauptsächlich, weil es das ist, was Phönix verwendet, und ich bin immer noch in der frühen Entwicklung ... und auch, Cowboy dient ziemlich gut statischen Inhalten, soweit ich weiß. Wenn ich die Reichweitenanfrage jedoch nicht ausführen kann, gehe ich vielleicht über Nginx und Reverse Proxy zu meinem Phönix-Server, aber ich würde es vorziehen, dies zu beheben. – TheSquad

Antwort

0

ich einen Weg gefunden, es selbst mit Steckern zu tun ... Also wenn jemand Reichweite Anfrage mit Phoenix/Elixir dienen will Hier ist, was Sie zu tun haben (Dies ist ziemlich einfach und tut berücksichtigen rfc nicht)

defmodule Plug.Range do                      
    @behaviour Plug                        
    @allowed_methods ~w(GET HEAD)                    
    import Plug.Conn                        

    def init(options) do                       
    options                         
    end                           

    def call(conn, _opts) do                      
    if (Enum.empty?(Plug.Conn.get_req_header(conn, "range"))) do            
     conn                          
    else                          
     file_path = "priv/static" <> conn.request_path               
     if File.exists? file_path do                    

     stats = File.stat! file_path                   
     filesize = stats.size                     

     req = Regex.run(~r/bytes=([0-9]+)-([0-9]+)?/, conn |> Plug.Conn.get_req_header("range") |> List.first) 

     {req_start, _} = req |> Enum.at(1) |> Integer.parse             
     {req_end, _} = req |> Enum.at(2, filesize |> to_string) |> Integer.parse        

     file_end = (filesize - 2) |> to_string                

     length = req_end - req_start + 1                  

     conn                         
     |> Plug.Conn.put_resp_header("Content-Type", "video/mp4")            
     |> Plug.Conn.put_resp_header("Accept-Ranges", "bytes")             
     |> Plug.Conn.put_resp_header("Content-Range", "bytes #{req_start}-#{req_end}/#{filesize}")    
     |> Plug.Conn.send_file(206, file_path, req_start, length)            
     |> Plug.Conn.halt                      
     else                          
     conn                         
     end                          
    end                          
    end                           
end   

Wie Sie, gerade jetzt sehen kann, wird es nur senden „video/mp4“ Content-Type, aber man kann leicht etwas Arbeit für alles ...

machen Endlich, damit der Plug funktioniert Sie müssen es direkt vor Plug.static in Ihrer Project-Endpoint-Datei platzieren.

Hoffe, dass es jemand hilft ...

EDIT: Für diejenigen, die interessiert sind, ich habe ein Github/hex.pm Paket für diese erstellt: Hex link
github link

0

Es ist wie Cowboy sieht nicht (noch) keine Unterstützung für die Range Header, so dass Sie ein verwenden, müssen dafür einen anderen Webserver.

Quelle: https://github.com/ninenines/cowboy/issues/306

+0

Sie haben Recht, Bereich wird noch nicht unterstützt, aber ich habe einen Weg gefunden, dies mit Plugs zu tun, siehe unten meine Antwort ... – TheSquad

+0

Ich persönlich hätte lieber eine RFC-konforme Implementierung. Aber wenn es für dich funktioniert, großartig! Prost ;-) –

+0

Das ist nur für Entwicklungszwecke ... Momentan habe ich leider keine Zeit, eine RFC-konforme Implementierung zu erstellen ... Ich werde wohl in einem Monat mit dem RFC-konformen Plug ein Github erstellen, dafür aber Jetzt wird es für mich funktionieren ;-) – TheSquad