Skip to content

Commit

Permalink
Merge pull request #4 from takutakahashi/webp
Browse files Browse the repository at this point in the history
Implemented WebP Convert
  • Loading branch information
takutakahashi authored Oct 12, 2023
2 parents 3d95a50 + 83e15ce commit 5cf2008
Show file tree
Hide file tree
Showing 6 changed files with 154 additions and 8 deletions.
6 changes: 5 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
go_version: [1.18, 1.19]
go_version: [ 1.18, 1.19 ]
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Install Dependencies
run: |
sudo apt update
sudo apt install -y webp
- name: Setup Go
uses: actions/setup-go@v3
with:
Expand Down
5 changes: 5 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,15 @@ WORKDIR /go/src/oyaki
COPY . /go/src/oyaki

RUN CGO_ENABLED=0 go build -ldflags "-s -w -X main.version=${OYAKI_VERSION}" -o /go/bin/oyaki
RUN apt update && apt install -y curl \
&& curl https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-1.3.1-linux-x86-64.tar.gz --output libwebp.tar.gz \
&& tar vzxf libwebp.tar.gz \
&& mv libwebp-1.3.1-linux-x86-64/bin/cwebp /go/bin/

FROM gcr.io/distroless/static-debian11

COPY --from=build /go/bin/oyaki /
COPY --from=build /go/bin/cwebp /bin/

EXPOSE 8080

Expand Down
Empty file added go.sum
Empty file.
35 changes: 28 additions & 7 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"net/http"
"net/url"
"os"
"path/filepath"
"runtime/debug"
"strconv"
"syscall"
Expand Down Expand Up @@ -77,12 +78,22 @@ func proxy(w http.ResponseWriter, r *http.Request) {
if len(xff) > 1 {
req.Header.Set("X-Forwarded-For", xff)
}

orgRes, err := client.Do(req)
if err != nil {
http.Error(w, "Get origin failed", http.StatusBadGateway)
log.Printf("Get origin failed. %v\n", err)
return
var orgRes *http.Response
pathExt := filepath.Ext(req.URL.Path)
if pathExt == ".webp" {
orgRes, err = doWebp(req)
if err != nil {
http.Error(w, "Get origin failed", http.StatusBadGateway)
log.Printf("Get origin failed. %v\n", err)
return
}
} else {
orgRes, err = client.Do(req)
if err != nil {
http.Error(w, "Get origin failed", http.StatusBadGateway)
log.Printf("Get origin failed. %v\n", err)
return
}
}
defer orgRes.Body.Close()

Expand Down Expand Up @@ -130,8 +141,18 @@ func proxy(w http.ResponseWriter, r *http.Request) {
return
}
defer buf.Reset()
if pathExt == ".webp" {
buf, err = convWebp(buf, []string{})
if err != nil {
http.Error(w, "image convert failed", http.StatusInternalServerError)
log.Printf("Read origin body failed. %v\n", err)
return

w.Header().Set("Content-Type", "image/jpeg")
}
w.Header().Set("Content-Type", "image/webp")
} else {
w.Header().Set("Content-Type", "image/jpeg")
}
w.Header().Set("Content-Length", strconv.Itoa(buf.Len()))

if _, err := io.Copy(w, buf); err != nil {
Expand Down
60 changes: 60 additions & 0 deletions webp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package main

import (
"bytes"
"fmt"
"io"
"log"
"net/http"
"net/url"
"os"
"os/exec"
)

func doWebp(req *http.Request) (*http.Response, error) {
var orgRes *http.Response
orgURL := req.URL
newPath := orgURL.Path[:len(orgURL.Path)-len(".webp")]
newOrgURL, err := url.Parse(fmt.Sprintf("%s://%s%s?%s", orgURL.Scheme, orgURL.Host, newPath, orgURL.RawQuery))
if err != nil {
log.Println(err)
return nil, err
}
newReq, err := http.NewRequest("GET", newOrgURL.String(), nil)
newReq.Header = req.Header
if err != nil {
log.Println(err)
return nil, err
}
orgRes, err = client.Do(newReq)
if err != nil {
log.Println(err)
return nil, err
}
if orgRes.StatusCode != 200 {
log.Println(orgRes.Status)
return nil, err
}
return orgRes, nil
}

func convWebp(src io.Reader, params []string) (*bytes.Buffer, error) {
f, err := os.CreateTemp("/tmp", "")
if err != nil {
return nil, err
}
defer f.Close()
defer os.Remove(f.Name())

_, err = io.Copy(f, src)
if err != nil {
return nil, err
}
params = append(params, "-quiet", "-mt", "-jpeg_like", f.Name(), "-o", "-")
out, err := exec.Command("cwebp", params...).Output()
if err != nil {
log.Println(err)
return nil, err
}
return bytes.NewBuffer(out), nil
}
56 changes: 56 additions & 0 deletions webp_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package main

import (
"io"
"net/http"
"net/http/httptest"
"testing"
)

func TestProxyWebP(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(proxy))

origin := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "./testdata/oyaki.jpg")
}))

orgSrvURL = origin.URL
url := ts.URL + "/oyaki.jpg.webp"

req, _ := http.NewRequest("GET", url, nil)
resp, err := doWebp(req)
if err != nil {
t.Fatal(err)
} else {
io.ReadAll(resp.Body)
resp.Body.Close()
}
// match with origin file info
if resp.Header.Get("Content-Type") != "image/jpeg" {
t.Error("wrong header Content-Type")
t.Error(resp.Header)
}
}

func TestConvJPG2WebP(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(proxy))

origin := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "./testdata/oyaki.jpg")
}))

orgSrvURL = origin.URL
url := ts.URL + "/oyaki.jpg.webp"

req, _ := http.NewRequest("GET", url, nil)
resp, err := doWebp(req)
if err != nil {
t.Fatal(err)
}
defer resp.Body.Close()
_, err = convWebp(resp.Body, []string{})
if err != nil {
t.Fatal(err)
}

}

0 comments on commit 5cf2008

Please sign in to comment.