save
This commit is contained in:
@@ -105,11 +105,112 @@ All commands are run from the root of the project, from a terminal:
|
||||
|
||||
| Command | Action |
|
||||
| :------------------------ | :----------------------------------------------- |
|
||||
| $$fes run .$$ | Runs the project at $$.$$ |
|
||||
| $$fes run .$$ | Runs the project at $$.$$ |
|
||||
|
||||
## Gemini
|
||||
|
||||
Fes supports many different protocols. One of which is the Gemini protocol; this
|
||||
protocol has specific encryption standards which makes the providing $$key.pem$$
|
||||
and a $$cert.pem$$ files. *Please* regenerate these files by running this command.
|
||||
$$$$$$
|
||||
openssl req -x509 -nodes -days 365 \
|
||||
-newkey rsa:2048 \
|
||||
-keyout key.pem \
|
||||
-out cert.pem \
|
||||
-subj "/C=US/ST=State/L=City/O=Local Development/OU=Localhost/CN=localhost" \
|
||||
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1,IP:::1" \
|
||||
-addext "basicConstraints=CA:FALSE" \
|
||||
-addext "keyUsage=digitalSignature,keyEncipherment" \
|
||||
-addext "extendedKeyUsage=serverAuth"
|
||||
$$$$$$
|
||||
|
||||
## What to learn more?
|
||||
|
||||
Check out [Fes's docs](https://docs.vxserver.dev/static/fes.html).`, "$$", "`"), dir, dir)
|
||||
write("key.pem", `-----BEGIN PRIVATE KEY-----
|
||||
MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQCfl+m81U9+WLBn
|
||||
PiJ1ZADnZC+BecXArguAdnbkgDlmfqe1eU6M0PBmXXFHEvJYOh2oYQZ7DMbuLLvo
|
||||
DdjomXM4yb9Axu2KDHfflTcw3wHD3850ganf9rwVG460gkVfUGaRiokyCvEJKd05
|
||||
BxKmx8Zh6G2tpetaDKm72ONYQFyaBCelYMzaBRpJ2kcPqk/gEhUSvQKVF4oDREm+
|
||||
sTEkCTWsjUesiG0393t3psFa/SlZKsNXNrb+N6y9SElKVlQOT28r9YGiDfy5PiAQ
|
||||
iFtQse2gqC4IhG2MGi0b4mu4Qa3+d2u3jsmn6Gqt92hKrbFOpz+Ci5GQ+zKXnE+j
|
||||
/h40l1J3h/aTM5/qS7malAtXySMVzLQnJzai6IL+nBKbIOMCzP1Bns64Oo7YuuhV
|
||||
Cx/sovrvgFF+8j4nLXOBgrx8llYB5cvgVYkNmccXtPzd7hZI6PHgZRGOd0uBKlZ+
|
||||
OHeKhgdnz/a+pCUBwJe8JAzX7fzoZ+HLy26ADx2Uywh0Rjfj4gVOSZXaGS0ne0p5
|
||||
PciN0xsWQdaAWPcVe6+YYRKS6l6qaWuGaPwVsZSvNgIMMPOgUn7+s2Bxh51DhqZT
|
||||
4MDFUJWXFmTnyhHg3Cq7pWJR7pv2erv5q32b8iah5o+CP4W3FeZX1CcBuiIsrimh
|
||||
vZZIa5W2vzpkLHbWgI2XGbx8yKRXowIDAQABAoICAENZb5lyB5cRRHh9XztdFYiQ
|
||||
3f9s7UhP6qiu1aO+fPrFDm9mHwEMF7eLTYep9j3HYMazE3IQRU8z76SRW21lfJuF
|
||||
gEGM8aeldV0UcnMcWXlY1J6ULaVHUb4yn/mLVE1R98cJyLYmqeutEB/F3VgmzJB6
|
||||
7vYuI/EfkO2mLOMMXkfc4wJGpIyJRLvP8tcoj4bG+r+qphFXGrYgNmLUEiHcBRup
|
||||
j4q/FCBfP2qSI90LI0zu3/rJK1aDFlHW1J8baWOUoBzUAX3rGzDth8iSUr7uJ5L6
|
||||
Blsvz68lSM4QslbS2OOfcATJrE5Apex+kTOas023BPVJgwfFCmey3mUdk4+sIG+I
|
||||
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
|
||||
h6CgX4Gc3+bhvKx36XYxVwScPJUWsQ==
|
||||
-----END PRIVATE KEY-----`)
|
||||
write("cert.pem", `-----BEGIN CERTIFICATE-----
|
||||
MIIFmzCCA4OgAwIBAgIUZGaMDLeCAQplfhhjXb2HaL6xpFYwDQYJKoZIhvcNAQEL
|
||||
BQAwXTELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVN0YXRlMQ0wCwYDVQQHDARDaXR5
|
||||
MQwwCgYDVQQKDANPcmcxDTALBgNVBAsMBFVuaXQxEjAQBgNVBAMMCWxvY2FsaG9z
|
||||
dDAeFw0yNjAyMjQwMjUwMzVaFw0yNzAyMjQwMjUwMzVaMF0xCzAJBgNVBAYTAlVT
|
||||
MQ4wDAYDVQQIDAVTdGF0ZTENMAsGA1UEBwwEQ2l0eTEMMAoGA1UECgwDT3JnMQ0w
|
||||
CwYDVQQLDARVbml0MRIwEAYDVQQDDAlsb2NhbGhvc3QwggIiMA0GCSqGSIb3DQEB
|
||||
AQUAA4ICDwAwggIKAoICAQCfl+m81U9+WLBnPiJ1ZADnZC+BecXArguAdnbkgDlm
|
||||
fqe1eU6M0PBmXXFHEvJYOh2oYQZ7DMbuLLvoDdjomXM4yb9Axu2KDHfflTcw3wHD
|
||||
3850ganf9rwVG460gkVfUGaRiokyCvEJKd05BxKmx8Zh6G2tpetaDKm72ONYQFya
|
||||
BCelYMzaBRpJ2kcPqk/gEhUSvQKVF4oDREm+sTEkCTWsjUesiG0393t3psFa/SlZ
|
||||
KsNXNrb+N6y9SElKVlQOT28r9YGiDfy5PiAQiFtQse2gqC4IhG2MGi0b4mu4Qa3+
|
||||
d2u3jsmn6Gqt92hKrbFOpz+Ci5GQ+zKXnE+j/h40l1J3h/aTM5/qS7malAtXySMV
|
||||
zLQnJzai6IL+nBKbIOMCzP1Bns64Oo7YuuhVCx/sovrvgFF+8j4nLXOBgrx8llYB
|
||||
5cvgVYkNmccXtPzd7hZI6PHgZRGOd0uBKlZ+OHeKhgdnz/a+pCUBwJe8JAzX7fzo
|
||||
Z+HLy26ADx2Uywh0Rjfj4gVOSZXaGS0ne0p5PciN0xsWQdaAWPcVe6+YYRKS6l6q
|
||||
aWuGaPwVsZSvNgIMMPOgUn7+s2Bxh51DhqZT4MDFUJWXFmTnyhHg3Cq7pWJR7pv2
|
||||
erv5q32b8iah5o+CP4W3FeZX1CcBuiIsrimhvZZIa5W2vzpkLHbWgI2XGbx8yKRX
|
||||
owIDAQABo1MwUTAdBgNVHQ4EFgQUcyq+ZZWmAUejOPEQpHpl4hOllHswHwYDVR0j
|
||||
BBgwFoAUcyq+ZZWmAUejOPEQpHpl4hOllHswDwYDVR0TAQH/BAUwAwEB/zANBgkq
|
||||
hkiG9w0BAQsFAAOCAgEANwdjxlPHqvOOyNTFJcFhcNff3862/74CyCiglrstk/ea
|
||||
txjyHxXFwXOtyAtm0tqaQPpzHWFM5MDqVD7Qip4aZrPcRvvfJ8zxXuakrgy7oI6i
|
||||
Wl4/BXzvIoxh8MyFVC7VdGmuv11fq091RaNPlnz5lH9Qxhb6QCGbk73PjTXxD/7A
|
||||
yusNiXuJvx3oRhLLGuksotFKEnngOq21Jla3ZPUmJTLAZdk/joXITk5Q64ZBp5uD
|
||||
rpxFZDtdHTBuL3nmNPUHixsxQRFzCSloufRlatdI2ldDc+d2WLLFhkpdM35Oedf3
|
||||
Hib0VXPgJ8j/w6RK+oYKMP27RojMFXALolzRBSQu3Zbd1bD1qVhh/dO5Uyn4E3mb
|
||||
2LW5+a9zuabD9wt8smSU9V5ZYw5hcR0ANN7xYmaMvGFKrNPNkI3m0c2dyj22vgg0
|
||||
zQqeMze4KxZqDf/gFifJ4UIybBAgc/p1uOIceFTSYplVXJQIgFACn9l6c4Zo0GZD
|
||||
H48iKQLwlxDdUSM8aHtItWxRddLCL7lYNKtu2/qu8I9NKkjx4/Kn3I9Is/f37EIn
|
||||
rF3ygUg3ee5zo3fvMjlhCNs6djm+ANx2KzdZkS7UU/jb0o+OSEvoMIgZh5NNgUlC
|
||||
aVR3opS3PTqwu4plN0Evh5kr3nEOx0vcIK726DwnpgNRhcG9cNcSi2UB4NYCWaw=
|
||||
-----END CERTIFICATE-----`)
|
||||
|
||||
ui.Hint("you can run this with `fes run %s`", dir)
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
@@ -95,15 +96,22 @@ func generateArchiveIndex(fsPath string, urlPath string) (string, error) {
|
||||
}
|
||||
|
||||
/* helper to read the archive files */
|
||||
func readArchive(w http.ResponseWriter, route string) error {
|
||||
fsPath := "." + route
|
||||
if info, err := os.Stat(fsPath); err == nil && info.IsDir() {
|
||||
if page, err := generateArchiveIndex(fsPath, route); err == nil {
|
||||
w.Write([]byte(page))
|
||||
return nil
|
||||
} else {
|
||||
return err
|
||||
func readArchive(w io.Writer, route string, protcol Protocols) error {
|
||||
switch protcol {
|
||||
case HTTP:
|
||||
fsPath := "." + route
|
||||
if info, err := os.Stat(fsPath); err == nil && info.IsDir() {
|
||||
if page, err := generateArchiveIndex(fsPath, route); err == nil {
|
||||
w.Write([]byte(page))
|
||||
return nil
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case GEMINI:
|
||||
panic(errors.New("TODO"))
|
||||
default:
|
||||
panic(errors.New("Invalid Protocol"))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -25,17 +25,9 @@ func geminiHandler(w gemini.ResponseWriter, r *gemini.Request) {
|
||||
route = r.URL.Path
|
||||
|
||||
if strings.HasPrefix(route, "/archive") {
|
||||
w.Write([]byte("# error: not implemented"))
|
||||
// err = readArchive(w, route)
|
||||
err = readArchive(w, route, GEMINI)
|
||||
} else {
|
||||
w.WriteHeader(gemini.StatusNotFound, "StatusNotFound")
|
||||
w.Write([]byte(`<html>
|
||||
<head><title>404 Not Found</title></head>
|
||||
<body>
|
||||
<center><h1>404 Not Found</h1></center>
|
||||
<hr><center>fes</center>
|
||||
</body>
|
||||
</html>`))
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -49,7 +41,7 @@ func geminiHandler(w gemini.ResponseWriter, r *gemini.Request) {
|
||||
|
||||
var data []byte
|
||||
if strings.HasSuffix(route, ".lua") {
|
||||
data, err = render(route, reqData{path: r.URL.Path, params: params}, &Sets)
|
||||
data, err = render(route, reqData{path: r.URL.Path, params: params}, GEMINI)
|
||||
} else if strings.HasSuffix(route, ".md") {
|
||||
data, err = os.ReadFile(route)
|
||||
data = []byte(markdownToHTML(string(data)))
|
||||
|
||||
@@ -26,7 +26,7 @@ func httpHandler(w http.ResponseWriter, r *http.Request) {
|
||||
route = r.URL.Path
|
||||
|
||||
if strings.HasPrefix(route, "/archive") {
|
||||
err = readArchive(w, route)
|
||||
err = readArchive(w, route, HTTP)
|
||||
} else {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write([]byte(`<html>
|
||||
@@ -49,7 +49,7 @@ func httpHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var data []byte
|
||||
if strings.HasSuffix(route, ".lua") {
|
||||
data, err = render(route, reqData{path: r.URL.Path, params: params}, &Sets)
|
||||
data, err = render(route, reqData{path: r.URL.Path, params: params}, HTTP)
|
||||
} else if strings.HasSuffix(route, ".md") {
|
||||
data, err = os.ReadFile(route)
|
||||
data = []byte(markdownToHTML(string(data)))
|
||||
|
||||
@@ -14,14 +14,7 @@ type reqData struct {
|
||||
params map[string]string
|
||||
}
|
||||
|
||||
type DeclarativeSets struct {
|
||||
protos struct {
|
||||
http bool
|
||||
gemini bool
|
||||
}
|
||||
}
|
||||
|
||||
func render(luapath string, requestData reqData, setBuffer *DeclarativeSets) ([]byte, error) {
|
||||
func render(luapath string, requestData reqData, protocol Protocols) ([]byte, error) {
|
||||
L := lua.NewState()
|
||||
defer L.Close()
|
||||
|
||||
@@ -74,6 +67,36 @@ func render(luapath string, requestData reqData, setBuffer *DeclarativeSets) ([]
|
||||
panic("fes module did not return table")
|
||||
}
|
||||
|
||||
if err := L.CallByParam(lua.P{
|
||||
Fn: L.GetGlobal("require"),
|
||||
NRet: 1,
|
||||
Protect: true,
|
||||
}, lua.LString("lib.std")); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
stdMod := L.Get(-1)
|
||||
L.Pop(1)
|
||||
|
||||
stdTbl, ok := stdMod.(*lua.LTable)
|
||||
if !ok {
|
||||
panic("lib.std did not return table")
|
||||
}
|
||||
|
||||
proto := func() string {
|
||||
switch protocol {
|
||||
case HTTP:
|
||||
return "http"
|
||||
case GEMINI:
|
||||
return "gemini"
|
||||
default:
|
||||
return "http"
|
||||
}
|
||||
}()
|
||||
|
||||
stdTbl.RawSetString("proto", lua.LString(proto))
|
||||
tbl.RawSetString("std", stdTbl)
|
||||
|
||||
bus := L.NewTable()
|
||||
bus.RawSetString("url", lua.LString(requestData.path))
|
||||
|
||||
|
||||
@@ -11,8 +11,14 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Protocols int
|
||||
|
||||
const (
|
||||
HTTP Protocols = iota
|
||||
GEMINI
|
||||
)
|
||||
|
||||
var Routes map[string]string
|
||||
var Sets DeclarativeSets
|
||||
|
||||
func Start(dir string) {
|
||||
if err := os.Chdir(dir); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user