120 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			120 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
/*
 | 
						|
Copyright © 2019 Darko Luketic <info@icod.de>
 | 
						|
 | 
						|
Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
you may not use this file except in compliance with the License.
 | 
						|
You may obtain a copy of the License at
 | 
						|
 | 
						|
    http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
 | 
						|
Unless required by applicable law or agreed to in writing, software
 | 
						|
distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
See the License for the specific language governing permissions and
 | 
						|
limitations under the License.
 | 
						|
*/
 | 
						|
package server
 | 
						|
 | 
						|
import (
 | 
						|
	"bytes"
 | 
						|
	"fmt"
 | 
						|
	"net/http"
 | 
						|
	"os/exec"
 | 
						|
	"syscall"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"github.com/allegro/bigcache"
 | 
						|
	"github.com/sirupsen/logrus"
 | 
						|
)
 | 
						|
 | 
						|
type Handler struct {
 | 
						|
	binary     string
 | 
						|
	baseParams []string
 | 
						|
	uid        int
 | 
						|
	logger     *logrus.Logger
 | 
						|
	cache      *bigcache.BigCache
 | 
						|
}
 | 
						|
 | 
						|
func NewHandler(binary string, eviction time.Duration) *Handler {
 | 
						|
	h := new(Handler)
 | 
						|
	h.binary = binary
 | 
						|
	h.uid = syscall.Getuid()
 | 
						|
	h.baseParams = []string{
 | 
						|
		"--disable-client-side-phishing-detection",
 | 
						|
		"--disable-cloud-import",
 | 
						|
		"--disable-default-apps",
 | 
						|
		"--disable-dinosaur-easter-egg",
 | 
						|
		"--disable-new-tab-first-run",
 | 
						|
		"--disable-offer-upload-credit-cards",
 | 
						|
		"--disable-signin-promo",
 | 
						|
		"--disable-sync",
 | 
						|
		"--disable-translate",
 | 
						|
		"--hide-scrollbars",
 | 
						|
		"--incognito",
 | 
						|
		"--mute-audio",
 | 
						|
		"--no-default-browser-check",
 | 
						|
		"--no-first-run",
 | 
						|
		"--noerrdialogs",
 | 
						|
		"--password-store=basic",
 | 
						|
		"--window-size=1280,1696",
 | 
						|
		"--headless",
 | 
						|
		"--disable-gpu",
 | 
						|
		"--disable-software-rasterizer",
 | 
						|
		"--dump-dom",
 | 
						|
	}
 | 
						|
	h.logger = logrus.StandardLogger()
 | 
						|
	cacheConf := bigcache.DefaultConfig(eviction)
 | 
						|
	cacheConf.HardMaxCacheSize = 500 * 1024 * 1024 // 500MB
 | 
						|
	cache, e := bigcache.NewBigCache(cacheConf)
 | 
						|
	if e != nil {
 | 
						|
		h.logger.Fatal(e.Error())
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
	h.cache = cache
 | 
						|
	return h
 | 
						|
}
 | 
						|
 | 
						|
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 | 
						|
	b, e := h.FetchDom(fmt.Sprintf("https://%s%s", r.Host, r.RequestURI))
 | 
						|
	if e != nil {
 | 
						|
		h.logger.Error(e)
 | 
						|
		if _, err := fmt.Fprintln(w, e.Error()); err != nil {
 | 
						|
			h.logger.Error(e)
 | 
						|
			return
 | 
						|
		}
 | 
						|
		return
 | 
						|
	}
 | 
						|
	if _, e := w.Write(b.Bytes()); e != nil {
 | 
						|
		h.logger.Error(e)
 | 
						|
	}
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
func (h *Handler) FetchDom(url string) (*bytes.Buffer, error) {
 | 
						|
	b, e := h.cache.Get(url)
 | 
						|
	if e != nil {
 | 
						|
		if e == bigcache.ErrEntryNotFound {
 | 
						|
			var params []string
 | 
						|
			if h.uid == 0 {
 | 
						|
				params = append(h.baseParams, "--no-sandbox")
 | 
						|
			} else {
 | 
						|
				params = h.baseParams
 | 
						|
			}
 | 
						|
			params = append(params, url)
 | 
						|
			cmd := exec.Command(h.binary, params...)
 | 
						|
			buf := bytes.NewBuffer(nil)
 | 
						|
			cmd.Stdout = buf
 | 
						|
			if e := cmd.Run(); e != nil {
 | 
						|
				return nil, e
 | 
						|
			}
 | 
						|
			if e := h.cache.Set(url, buf.Bytes()); e != nil {
 | 
						|
				h.logger.Error(e)
 | 
						|
			}
 | 
						|
			return buf, nil
 | 
						|
		} else {
 | 
						|
			return nil, e
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return bytes.NewBuffer(b), nil
 | 
						|
}
 |