-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
e2e regression tests: HTTP caching proxy, new cases #633
Merged
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
5c72ea8
e2e: new use case: runtime txs, events
mitjat f8f3dec
kvstore: Extract into new package
mitjat e5e6073
Implement caching_http_proxy
mitjat 3a935e5
cmd/analyzer: run caching_http_proxy as helper
mitjat 8a43600
analyzer/item: Do not sleep on start
mitjat 87da639
analyzer/item: Do not exit immediately on empty queue
mitjat a9be27d
analyzer/evmverifier: Use upsert, allow short query intervals
mitjat 6c5721c
rename helpers -> cachingProxies
mitjat abbd836
analyzers: close caching proxies on termination
mitjat 91dd3b8
e2e_regression: cache: Do not track index files in git
mitjat 12458fe
e2e: accept-e2e-regression: Do nothing if there are no outputs.
mitjat aa761a4
e2e: Update outputs
mitjat 534a3b1
Revert "e2e_regression: cache: Do not track index files in git"
mitjat File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 |
---|---|---|
|
@@ -9,6 +9,5 @@ docker/node/etc/genesis.json | |
tests/e2e/testnet/net-runner | ||
|
||
# Local workdirs | ||
cache | ||
.* | ||
*.log |
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 |
---|---|---|
|
@@ -14,7 +14,6 @@ tests/e2e_regression/*/actual/* | |
|
||
# Log output. | ||
**/*.log | ||
/cache | ||
/logs | ||
|
||
# API files. | ||
|
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
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
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
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
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
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,106 @@ | ||
package httpproxy | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"io" | ||
"net/http" | ||
"net/url" | ||
"path/filepath" | ||
"regexp" | ||
"time" | ||
|
||
"github.com/oasisprotocol/nexus/cache/kvstore" | ||
cmdCommon "github.com/oasisprotocol/nexus/cmd/common" | ||
"github.com/oasisprotocol/nexus/config" | ||
) | ||
|
||
// cachingHttpProxy is a minimal HTTP handler that caches responses; it is inteded *for testing only* | ||
// and comes with several caveats: | ||
// - The cache is never invalidated. | ||
// - All requests are forwarded to the same target host. | ||
// - Requests are cached based on the full URL, NOT the headers or the method (GET vs POST) or the request body. | ||
// - Low-likelihood errors (e.g. malformed URLs) result in panics. | ||
type cachingHttpProxy struct { | ||
client *http.Client | ||
cache kvstore.KVStore | ||
targetHost string // Must include the protocol (e.g. "http://") | ||
} | ||
|
||
var _ http.Handler = (*cachingHttpProxy)(nil) | ||
|
||
type CacheableResponse struct { | ||
StatusCode int | ||
Header http.Header | ||
Body []byte | ||
} | ||
|
||
func (p cachingHttpProxy) ServeHTTP(w http.ResponseWriter, req *http.Request) { | ||
// Rewrite the request URL to new host | ||
targetURL, _ := url.JoinPath(p.targetHost, req.URL.RequestURI()) | ||
req, err := http.NewRequestWithContext(req.Context(), req.Method, targetURL, req.Body) | ||
if err != nil { | ||
panic(fmt.Sprintf("error rewriting request to %s %s: %v", req.Method, req.URL.String(), err)) | ||
} | ||
|
||
// Get the response to the modified request (via cache) | ||
cResp, err := kvstore.GetFromCacheOrCall(p.cache, false, kvstore.CacheKey(req.URL.RequestURI()), func() (*CacheableResponse, error) { | ||
resp, err2 := p.client.Do(req) | ||
if err2 != nil { | ||
return nil, err2 | ||
} | ||
defer resp.Body.Close() | ||
body, err2 := io.ReadAll(resp.Body) | ||
if err2 != nil { | ||
return nil, fmt.Errorf("error reading response body from %s: %v", resp.Request.URL.String(), err2) | ||
} | ||
return &CacheableResponse{ | ||
StatusCode: resp.StatusCode, | ||
Header: resp.Header, | ||
Body: body, | ||
}, nil | ||
}) | ||
if err != nil { | ||
cResp = &CacheableResponse{ | ||
StatusCode: http.StatusInternalServerError, | ||
Header: http.Header{}, | ||
Body: []byte(fmt.Sprintf("error proxying request: %v", err)), | ||
} | ||
} | ||
|
||
// Write out the response to `w`. | ||
for key, values := range cResp.Header { | ||
for _, value := range values { | ||
w.Header().Add(key, value) | ||
} | ||
} | ||
w.WriteHeader(cResp.StatusCode) // 200, 404, etc | ||
if _, err = io.Copy(w, bytes.NewReader(cResp.Body)); err != nil { | ||
panic(err) | ||
} | ||
} | ||
|
||
// Creates a http.Server that proxies all requests to the target URL. | ||
// The server caches all responses in a persisted key-value store, located in an | ||
// autogenerated subdirectory of the cache root dir. | ||
func NewHttpServer(cacheCfg config.CacheConfig, proxyCfg config.HttpCachingProxyConfig) (*http.Server, error) { | ||
// Derive the cache root dir from the target URL. | ||
cleanTargetUrl := regexp.MustCompile("[^a-zA-Z0-9]+").ReplaceAllString(proxyCfg.TargetURL, "_") | ||
cachePath := filepath.Join(cacheCfg.CacheDir, cleanTargetUrl) | ||
kvStore, err := kvstore.OpenKVStore(cmdCommon.RootLogger().WithModule("caching-http-proxy"), cachePath, nil) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
handler := cachingHttpProxy{ | ||
client: &http.Client{}, | ||
cache: kvStore, | ||
targetHost: proxyCfg.TargetURL, | ||
} | ||
|
||
return &http.Server{ | ||
Addr: proxyCfg.HostAddr, | ||
Handler: handler, | ||
ReadHeaderTimeout: time.Second, | ||
}, nil | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm is there a case where the verifier would upsert rather than update? The
GetItems
query fetches candidates from thechain.evm_contracts
table originallyThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An insert can happen if sourcify has a contract that we haven't encountered yet, e.g. because we're scanning just a subset of blocks. GetItems no longer limits the items to
chain.evm_contracts
addresses as of #634 (which is not merged; I accidentally merged it into this branch and then undid that, but I'll duplicate the PR to merge intomain
once this PR goes in). The reasons for the change are pretty lightweight: we now don't have to worry about what happens as the number of contracts grows, and I found the new flow easier to understand, especially with the added partial/full verification.