-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
♻️ refactor: Refactoring to Go for performance and fix buffer overflo…
…w erros
- Loading branch information
1 parent
6f3e071
commit a89357f
Showing
13 changed files
with
283 additions
and
124 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
name: Deploy to GitHub Container Registry | ||
|
||
on: | ||
push: | ||
branches: | ||
- main | ||
workflow_dispatch: | ||
workflow_call: | ||
|
||
env: | ||
IMAGE_NAME: youtubei-proxy | ||
|
||
jobs: | ||
push: | ||
runs-on: ubuntu-latest | ||
permissions: | ||
packages: write | ||
contents: read | ||
steps: | ||
- uses: actions/checkout@v4 | ||
|
||
- name: Set up QEMU | ||
uses: docker/setup-qemu-action@v3 | ||
|
||
- name: Set up Docker Buildx | ||
uses: docker/setup-buildx-action@v3 | ||
|
||
- id: dockertag | ||
name: Get Docker tag | ||
uses: ASzc/change-string-case-action@v6 | ||
with: | ||
string: ghcr.io/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:latest | ||
|
||
- name: Log in to registry | ||
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin | ||
|
||
- name: Build and push | ||
uses: docker/build-push-action@v6 | ||
with: | ||
context: . | ||
platforms: linux/amd64,linux/arm64 | ||
push: true | ||
tags: ${{ steps.dockertag.outputs.lowercase }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,17 @@ | ||
{ | ||
"deno.enable": true | ||
"editor.formatOnSave": true, | ||
|
||
"[go]": { | ||
"editor.formatOnSave": true, | ||
"editor.codeActionsOnSave": { | ||
"source.organizeImports": "explicit" | ||
} | ||
}, | ||
|
||
"[go.mod]": { | ||
"editor.formatOnSave": true, | ||
"editor.codeActionsOnSave": { | ||
"source.organizeImports": "explicit" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
FROM golang:1.23.1-alpine | ||
WORKDIR /usr/src/app | ||
|
||
# Effectively tracks changes within your go.mod file | ||
COPY src/go.mod . | ||
COPY src/go.sum . | ||
RUN go mod download | ||
|
||
# Copies your source code into the app directory | ||
COPY src/main.go . | ||
RUN go build -o proxy | ||
|
||
# Run the app | ||
EXPOSE 8123/tcp | ||
|
||
CMD ["./proxy"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# Youtubei (Innertube) Proxy written in Go | ||
|
||
To install dependencies: | ||
|
||
```bash | ||
go install | ||
``` | ||
|
||
To run: | ||
|
||
```bash | ||
go run main.go | ||
``` | ||
|
||
This project was created using go v1.23.1. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
version: "3.8" | ||
|
||
services: | ||
youtubei-proxy: | ||
container_name: youtubei-proxy | ||
image: ghcr.io/waktaplay/youtubei-proxy:latest | ||
ports: | ||
- "8123:8123" | ||
networks: | ||
- nginx-bridge | ||
restart: always | ||
|
||
networks: | ||
nginx-bridge: | ||
external: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# This file was created with ignofier | ||
|
||
# If you prefer the allow list template instead of the deny list, see community template: | ||
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore | ||
# | ||
# Binaries for programs and plugins | ||
*.exe | ||
*.exe~ | ||
*.dll | ||
*.so | ||
*.dylib | ||
|
||
# Test binary, built with `go test -c` | ||
*.test | ||
|
||
# Output of the go coverage tool, specifically when used with LiteIDE | ||
*.out | ||
|
||
# Dependency directories (remove the comment below to include it) | ||
# vendor/ | ||
|
||
# Go workspace file | ||
go.work | ||
go.work.sum | ||
|
||
# env file | ||
.env |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
module youtubei_proxy | ||
|
||
go 1.23.1 | ||
|
||
require ( | ||
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be | ||
golang.org/x/net v0.29.0 | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be h1:J5BL2kskAlV9ckgEsNQXscjIaLiOYiZ75d4e94E6dcQ= | ||
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be/go.mod h1:mk5IQ+Y0ZeO87b858TlA645sVcEcbiX6YqP98kt+7+w= | ||
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= | ||
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"io" | ||
"log" | ||
"os" | ||
"time" | ||
|
||
"net/http" | ||
"net/url" | ||
|
||
"encoding/json" | ||
"github.com/common-nighthawk/go-figure" | ||
"golang.org/x/net/proxy" | ||
) | ||
|
||
const ( | ||
PORT = 8123 | ||
CHUNK_SIZE = 10 * 1024 * 1024 // 10MB | ||
) | ||
|
||
func copyHeader(headerName string, to http.Header, from http.Header) { | ||
hdrVal := from.Get(headerName) | ||
if hdrVal != "" { | ||
to.Set(headerName, hdrVal) | ||
} | ||
} | ||
|
||
func handler(w http.ResponseWriter, req *http.Request) { | ||
method := req.Method | ||
headers := req.Header | ||
urlStr := req.URL.String() | ||
|
||
// CORS preflight 처리 | ||
if method == http.MethodOptions { | ||
w.Header().Set("Access-Control-Allow-Origin", headers.Get("Origin")) | ||
w.Header().Set("Access-Control-Allow-Methods", "*") | ||
w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization") | ||
w.WriteHeader(http.StatusOK) | ||
return | ||
} | ||
|
||
urlObj, err := url.Parse(urlStr) | ||
if err != nil { | ||
http.Error(w, "Invalid URL", http.StatusBadRequest) | ||
return | ||
} | ||
|
||
if !urlObj.Query().Has("__host") { | ||
http.Error(w, "Request is formatted incorrectly. Please include __host in the query string.", http.StatusBadRequest) | ||
return | ||
} | ||
|
||
urlObj.Scheme = "https" | ||
urlObj.Host = urlObj.Query().Get("__host") | ||
query := urlObj.Query() | ||
query.Del("__host") | ||
urlObj.RawQuery = query.Encode() | ||
|
||
// 헤더 복사 | ||
requestHeaders := make(http.Header) | ||
if headersStr := urlObj.Query().Get("__headers"); headersStr != "" { | ||
json.Unmarshal([]byte(headersStr), &requestHeaders) | ||
} | ||
copyHeader("User-Agent", requestHeaders, headers) | ||
query.Del("__headers") | ||
urlObj.RawQuery = query.Encode() | ||
|
||
proxyURL := os.Getenv("PROXY") | ||
client := &http.Client{ | ||
Transport: &http.Transport{ | ||
MaxIdleConns: 100, | ||
MaxIdleConnsPerHost: 10, | ||
IdleConnTimeout: 90 * time.Second, | ||
}, | ||
} | ||
|
||
if proxyURL != "" { | ||
proxyURLParsed, err := url.Parse(proxyURL) | ||
if err == nil { | ||
dialer, err := proxy.FromURL(proxyURLParsed, proxy.Direct) | ||
if err == nil { | ||
transport := &http.Transport{Dial: dialer.Dial} | ||
client.Transport = transport | ||
} | ||
} | ||
} | ||
|
||
// 청크 단위로 요청 | ||
chunkStart := 0 | ||
for { | ||
chunkEnd := chunkStart + CHUNK_SIZE - 1 | ||
if chunkEnd < 0 { | ||
break | ||
} | ||
|
||
proxyReq, err := http.NewRequest(method, urlObj.String(), nil) | ||
if err != nil { | ||
log.Fatal("Failed to create request", err) | ||
http.Error(w, "Failed to create request", http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
// Range 헤더 설정 | ||
proxyReq.Header = requestHeaders | ||
proxyReq.Header.Set("Range", fmt.Sprintf("bytes=%d-%d", chunkStart, chunkEnd)) | ||
|
||
fetchRes, err := client.Do(proxyReq) | ||
if err != nil { | ||
log.Fatal("Failed to fetch response", err) | ||
http.Error(w, "Failed to fetch response", http.StatusInternalServerError) | ||
return | ||
} | ||
defer fetchRes.Body.Close() | ||
|
||
// 응답 처리 | ||
if fetchRes.StatusCode != http.StatusPartialContent { | ||
break | ||
} | ||
|
||
// 응답 스트림을 클라이언트에 전달 | ||
if _, err := io.Copy(w, fetchRes.Body); err != nil { | ||
log.Printf("Error writing response: %v", err) | ||
return | ||
} | ||
|
||
chunkStart += CHUNK_SIZE // 다음 청크로 이동 | ||
} | ||
} | ||
|
||
func main() { | ||
fig := figure.NewFigure("Innertube Proxy", "doom", true) | ||
fmt.Println(fig.String()) | ||
fmt.Println("----------------------------------------------------------------") | ||
|
||
http.HandleFunc("/", handler) | ||
log.Printf("[INFO] Server is running on port %d.\n", PORT) | ||
log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", PORT), nil)) | ||
} |
Oops, something went wrong.