[archiver] Add initial support for redirects file.
This commit is contained in:
parent
16efc8f8fc
commit
d55dbe84e8
1 changed files with 196 additions and 0 deletions
|
@ -13,6 +13,7 @@ import "io"
|
|||
import "io/ioutil"
|
||||
import "log"
|
||||
import "net/http"
|
||||
import "net/url"
|
||||
import "os"
|
||||
import "path/filepath"
|
||||
import "runtime"
|
||||
|
@ -335,6 +336,44 @@ func archiveReferenceAndData (_context *context, _namespace string, _pathResolve
|
|||
}
|
||||
|
||||
|
||||
func archiveReferenceAndDataWithMeta (_context *context, _namespace string, _pathInArchive string, _dataContent []byte, _dataMeta map[string]string) (string, string, error) {
|
||||
|
||||
var _fingerprintContent string
|
||||
var _fingerprintMeta string
|
||||
var _dataMetaRaw []byte
|
||||
|
||||
_fingerprintContentRaw := blake3.Sum256 (_dataContent)
|
||||
_fingerprintContent = hex.EncodeToString (_fingerprintContentRaw[:])
|
||||
|
||||
if _wasStored, _ := _context.storedDataContent[_fingerprintContent]; _wasStored {
|
||||
_dataContent = nil
|
||||
}
|
||||
|
||||
if _fingerprintMeta_0, _dataMetaRaw_0, _error := prepareDataMeta (_context, _dataMeta); _error != nil {
|
||||
return "", "", _error
|
||||
} else {
|
||||
_fingerprintMeta = _fingerprintMeta_0
|
||||
_dataMetaRaw = _dataMetaRaw_0
|
||||
}
|
||||
|
||||
if _error := archiveReference (_context, _namespace, _pathInArchive, _fingerprintContent, _fingerprintMeta); _error != nil {
|
||||
return "", "", _error
|
||||
}
|
||||
if _dataMetaRaw != nil {
|
||||
if _error := archiveDataMeta (_context, _fingerprintMeta, _dataMetaRaw); _error != nil {
|
||||
return "", "", _error
|
||||
}
|
||||
}
|
||||
if _dataContent != nil {
|
||||
if _error := archiveDataContent (_context, _fingerprintContent, _dataContent); _error != nil {
|
||||
return "", "", _error
|
||||
}
|
||||
}
|
||||
|
||||
return _fingerprintContent, _fingerprintMeta, nil
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
func archiveDataContent (_context *context, _fingerprintContent string, _dataContent []byte) (error) {
|
||||
|
@ -926,6 +965,8 @@ func walkPath (_context *context, _pathResolved string, _pathInArchive string, _
|
|||
var _wildcardName string
|
||||
var _wildcardStatus uint
|
||||
|
||||
var _redirectsName string
|
||||
|
||||
if _context.debug {
|
||||
log.Printf ("[dd] [2d22d910] folder |> `%s`\n", _pathInArchive)
|
||||
}
|
||||
|
@ -969,6 +1010,13 @@ func walkPath (_context *context, _pathResolved string, _pathInArchive string, _
|
|||
_wildcardStatus = 404
|
||||
continue
|
||||
}
|
||||
if (_childName == "_redirects") || (_childName == "_redirects.txt") {
|
||||
if _redirectsName != "" {
|
||||
return nil, fmt.Errorf ("[fbc0ee12] duplicate redirects files found: `%s` and `%s`!", _childName, _redirectsName)
|
||||
}
|
||||
_redirectsName = _childName
|
||||
continue
|
||||
}
|
||||
if ShouldSkipName (_childName) {
|
||||
if _context.debug {
|
||||
log.Printf ("[dd] [f11b5ba1] skip !! `%s`\n", _childPathInArchive)
|
||||
|
@ -1008,6 +1056,16 @@ func walkPath (_context *context, _pathResolved string, _pathInArchive string, _
|
|||
return nil, _error
|
||||
}
|
||||
}
|
||||
if _redirectsName != "" {
|
||||
_childPathInArchive := _pathInArchive
|
||||
_childPathResolved := _childsPathResolved[_redirectsName]
|
||||
if _context.debug {
|
||||
log.Printf ("[dd] [f49aa9f5] redirects -- `%s` -> `%s`\n", _childPathInArchive, _childPathResolved)
|
||||
}
|
||||
if _error := walkRedirects (_context, _childPathResolved, _childPathInArchive); _error != nil {
|
||||
return nil, _error
|
||||
}
|
||||
}
|
||||
|
||||
if _context.debug {
|
||||
log.Printf ("[dd] [ce1fe181] folder |> `%s`\n", _pathInArchive)
|
||||
|
@ -1048,6 +1106,144 @@ func walkPath (_context *context, _pathResolved string, _pathInArchive string, _
|
|||
|
||||
|
||||
|
||||
func walkRedirects (_context *context, _pathResolved string, _pathInArchive string) (error) {
|
||||
|
||||
_redirectsData, _error := os.ReadFile (_pathResolved)
|
||||
if _error != nil {
|
||||
return _error
|
||||
}
|
||||
|
||||
_redirectLines := strings.Split (string (_redirectsData), "\n")
|
||||
|
||||
for _, _redirectLine := range _redirectLines {
|
||||
|
||||
_redirectLine = strings.ReplaceAll (_redirectLine, "\t", " ")
|
||||
_redirectLine = strings.Trim (_redirectLine, " ")
|
||||
for {
|
||||
_redirectLine_0 := strings.ReplaceAll (_redirectLine, " ", " ")
|
||||
if _redirectLine == _redirectLine_0 {
|
||||
break
|
||||
}
|
||||
_redirectLine = _redirectLine_0
|
||||
}
|
||||
|
||||
if _redirectLine == "" {
|
||||
continue
|
||||
}
|
||||
if _redirectLine[0] == '#' {
|
||||
continue
|
||||
}
|
||||
|
||||
_redirectParts := strings.Split (_redirectLine, " ")
|
||||
if len (_redirectParts) != 3 {
|
||||
return fmt.Errorf ("[bf358c0a] invalid redirect statement: `%s` -- `%s`!", _pathResolved, _redirectLine)
|
||||
}
|
||||
|
||||
_source := _redirectParts[0]
|
||||
_target := _redirectParts[1]
|
||||
_code := 0
|
||||
switch _redirectParts[2] {
|
||||
case "301" : _code = 301
|
||||
case "302" : _code = 302
|
||||
case "303" : _code = 303
|
||||
case "307" : _code = 307
|
||||
case "308" : _code = 308
|
||||
default :
|
||||
return fmt.Errorf ("[fb9ac5a5] invalid redirect code: `%s` -- `%s`!", _pathResolved, _redirectLine)
|
||||
}
|
||||
|
||||
_sourceParsed := false
|
||||
if ! _sourceParsed {
|
||||
for _, _schemePrefix := range []string { "://", "http://", "https://" } {
|
||||
if strings.HasPrefix (_source, _schemePrefix) {
|
||||
if _pathInArchive != "/" {
|
||||
return fmt.Errorf ("[ceac537a] invalid redirect absolute source: `%s` -- `%s`!", _pathResolved, _redirectLine)
|
||||
}
|
||||
_source_0 := "http://" + strings.TrimPrefix (_source, _schemePrefix)
|
||||
_sourceUrl, _error := url.ParseRequestURI (_source_0)
|
||||
if _error != nil {
|
||||
return fmt.Errorf ("[dd43230e] invalid redirect source: `%s` -- `%s`!", _pathResolved, _redirectLine)
|
||||
}
|
||||
_sourceCanonical := _sourceUrl.String ()
|
||||
if _sourceCanonical != _source_0 {
|
||||
return fmt.Errorf ("[2c6dc950] invalid redirect source: `%s` -- `%s`!", _pathResolved, _redirectLine)
|
||||
}
|
||||
_source = strings.TrimPrefix (_source, _schemePrefix)
|
||||
_source = "://" + _source
|
||||
_sourceParsed = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if ! _sourceParsed {
|
||||
if _source[0] == '.' {
|
||||
if _pathInArchive == "/" {
|
||||
_source = "/" + _source[2:]
|
||||
} else {
|
||||
_source = _pathInArchive + "/" + _source[2:]
|
||||
}
|
||||
} else if _source[0] == '/' {
|
||||
if _pathInArchive != "/" {
|
||||
return fmt.Errorf ("[99e025fe] invalid redirect absolute source: `%s` -- `%s`!", _pathResolved, _redirectLine)
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf ("[2e716cd2] invalid redirect source: `%s` -- `%s`!", _pathResolved, _redirectLine)
|
||||
}
|
||||
_sourceUrl, _error := url.ParseRequestURI (_source)
|
||||
if _error != nil {
|
||||
return fmt.Errorf ("[be9abd4d] invalid redirect source: `%s` -- `%s`!", _pathResolved, _redirectLine)
|
||||
}
|
||||
_sourceCanonical := _sourceUrl.String ()
|
||||
if _sourceCanonical != _source {
|
||||
return fmt.Errorf ("[3c31deb4] invalid redirect source: `%s` -- `%s`!", _pathResolved, _redirectLine)
|
||||
}
|
||||
_sourceParsed = true
|
||||
}
|
||||
if ! _sourceParsed {
|
||||
return fmt.Errorf ("[8305376f] invalid redirect source: `%s` -- `%s`!", _pathResolved, _redirectLine)
|
||||
}
|
||||
|
||||
{
|
||||
_targetUrl, _error := url.Parse (_target)
|
||||
if _error != nil {
|
||||
return fmt.Errorf ("[968f7208] invalid redirect target: `%s` -- `%s`!", _pathResolved, _redirectLine)
|
||||
}
|
||||
_targetCanonical := _targetUrl.String ()
|
||||
if _targetCanonical != _target {
|
||||
return fmt.Errorf ("[c22eea24] invalid redirect target: `%s` -- `%s`!", _pathResolved, _redirectLine)
|
||||
}
|
||||
}
|
||||
|
||||
if _context.debug {
|
||||
log.Printf ("[dd] [c8139953] redirect -- `%s` -> `%s` (%d)\n", _source, _target, _code)
|
||||
}
|
||||
|
||||
_dataMeta := map[string]string {
|
||||
"!Status" : fmt.Sprintf ("%d", _code),
|
||||
"Location" : _target,
|
||||
}
|
||||
|
||||
_fingerprintContentRaw := blake3.Sum256 ([]byte (_redirectLine))
|
||||
_fingerprintContent := hex.EncodeToString (_fingerprintContentRaw[:])
|
||||
|
||||
if _context.includeCache {
|
||||
_dataMeta["Cache-Control"] = "public, immutable, max-age=3600"
|
||||
}
|
||||
if _context.includeEtag {
|
||||
_dataMeta["ETag"] = _fingerprintContent
|
||||
}
|
||||
|
||||
if _, _, _error := archiveReferenceAndDataWithMeta (_context, NamespaceFilesContent, _source, []byte (""), _dataMeta); _error != nil {
|
||||
return _error
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
func Main () () {
|
||||
|
||||
if len (os.Args) == 2 {
|
||||
|
|
Loading…
Reference in a new issue