-
-
Notifications
You must be signed in to change notification settings - Fork 30
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
Support NotSet string behavior in falco #248
Open
ysugimoto
wants to merge
20
commits into
main
Choose a base branch
from
feat/re-implementation-for-header-value
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 16 commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
6cb06ee
WIP: define LenientString, HttpHeader
ysugimoto f08521b
WIP: refactor transport and director, create falco http related struct
ysugimoto 6efb4fb
fix variables
ysugimoto 5501ff5
fix up value and variable considering lenient string
ysugimoto c1a7165
wip: builtin functions
ysugimoto 88c1a81
Merge remote-tracking branch 'origin/main' into feat/re-implementatio…
ysugimoto 94afef2
upstream main
ysugimoto 97eea38
pass interpreter tests with Lenient String
ysugimoto 74ba597
avoid nil pointer panic
ysugimoto 7069e59
fix built-in functions for lenient string
ysugimoto 9a24af4
change process pointer as Public
ysugimoto 52ed72e
linting
ysugimoto 33821d6
divide testing vcl files
ysugimoto 2e79923
add comment for refered issue URL
ysugimoto bf747c7
tidy mod
ysugimoto 3dcfbd2
remove unused function
ysugimoto 1edace3
fix typo and reflect reviews
ysugimoto 3d944df
resolve conflict
ysugimoto 5e786ac
remove unnecessary rand initialization
ysugimoto 0850dae
fix failing test after merged #254
ysugimoto 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 |
---|---|---|
|
@@ -17,6 +17,7 @@ | |
dist/* | ||
playground | ||
tools | ||
local | ||
|
||
.vscode | ||
|
||
|
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
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Empty file.
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,49 @@ | ||
// see: https://github.com/ysugimoto/falco/issues/237 | ||
|
||
// @scope: recv | ||
// @suite: ADD header(add-add-add) BUGGY | ||
sub test_recv { | ||
add req.http.VALUE = "V1"; | ||
add req.http.VALUE = "V2"; | ||
add req.http.VALUE = "V3"; | ||
assert.equal(req.http.VALUE, "V1"); # request upstream with 3 line headers | ||
|
||
set req.http.MESSAGE = req.http.VALUE; # set first header value | ||
assert.equal(req.http.MESSAGE, "V1"); | ||
} | ||
|
||
// @scope: recv | ||
// @suite: ADD header(set-add-add) BUGGY | ||
sub test_recv { | ||
set req.http.VALUE = "V1"; | ||
add req.http.VALUE = "V2"; | ||
add req.http.VALUE = "V3"; | ||
assert.equal(req.http.VALUE, "V1"); # request upstream with 3 headers | ||
|
||
set req.http.MESSAGE = req.http.VALUE; # set first header value | ||
assert.equal(req.http.MESSAGE, "V1"); | ||
} | ||
|
||
// @scope: recv | ||
// @suite: ADD header(add-add-set) | ||
sub test_recv { | ||
add req.http.VALUE = "V1"; | ||
add req.http.VALUE = "V2"; | ||
set req.http.VALUE = "V3"; | ||
assert.equal(req.http.VALUE, "V3"); # 1 header | ||
|
||
set req.http.MESSAGE = req.http.VALUE; | ||
assert.equal(req.http.MESSAGE, "V3"); | ||
} | ||
|
||
// @scope: recv | ||
// @suite: UNSET header(add-add-unset) | ||
sub test_recv { | ||
add req.http.VALUE = "V1"; | ||
add req.http.VALUE = "V2"; | ||
unset req.http.VALUE; | ||
assert.is_notset(req.http.VALUE); # 0 header | ||
|
||
set req.http.MESSAGE = req.http.VALUE; | ||
assert.equal(req.http.MESSAGE, "(null)"); | ||
} |
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 @@ | ||
// empty VCL |
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,34 @@ | ||
// see: https://github.com/ysugimoto/falco/issues/235 | ||
|
||
// @scope: recv | ||
// @suite: UNSET header | ||
sub test_recv { | ||
set req.http.VALUE = "V"; | ||
unset req.http.VALUE; | ||
assert.is_notset(req.http.VALUE); | ||
|
||
set req.http.MESSAGE = req.http.VALUE; | ||
assert.equal(req.http.MESSAGE, "(null)"); | ||
} | ||
|
||
// @scope: recv | ||
// @suite: EMPTY header | ||
sub test_recv { | ||
set req.http.VALUE = "V"; | ||
set req.http.VALUE = ""; | ||
assert.equal(req.http.VALUE, ""); | ||
|
||
set req.http.MESSAGE = req.http.VALUE; | ||
assert.equal(req.http.MESSAGE, ""); | ||
} | ||
|
||
// @scope: recv | ||
// @suite: NOTSET header | ||
sub test_recv { | ||
set req.http.VALUE = "V"; | ||
set req.http.VALUE = req.http.NOTSET; | ||
assert.is_notset(req.http.VALUE); | ||
|
||
set req.http.MESSAGE = req.http.VALUE; | ||
assert.equal(req.http.MESSAGE, "(null)"); | ||
} |
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 @@ | ||
// empty VCL |
79 changes: 79 additions & 0 deletions
79
examples/testing/objective_header/objective_header.test.vcl
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,79 @@ | ||
// see: https://github.com/ysugimoto/falco/issues/236 | ||
|
||
// @scope: recv | ||
// @suite: SET VARS VALUE | ||
sub test_recv { | ||
set req.http.VARS = ""; | ||
set req.http.VARS:VALUE = "V"; | ||
assert.equal(req.http.VARS, "VALUE=V"); | ||
} | ||
|
||
// @scope: recv | ||
// @suite: SET NOT-INITIALIZED VARS VALUE | ||
sub test_recv { | ||
set req.http.VARS:VALUE = "V"; | ||
assert.equal(req.http.VARS, "VALUE=V"); | ||
} | ||
|
||
// @scope: recv | ||
// @suite: SET MULTIPLE VARS VALUE | ||
sub test_recv { | ||
set req.http.VARS = ""; | ||
set req.http.VARS:VALUE = "V"; | ||
set req.http.VARS:VALUE2 = "V2"; | ||
assert.equal(req.http.VARS, "VALUE=V, VALUE2=V2"); | ||
} | ||
|
||
// @scope: recv | ||
// @suite: SET EMPTY VARS VALUE | ||
sub test_recv { | ||
set req.http.VARS = ""; | ||
set req.http.VARS:VALUE = ""; | ||
assert.equal(req.http.VARS, "VALUE"); | ||
} | ||
|
||
// @scope: recv | ||
// @suite: SET MULTIPLE EMPTY VARS VALUE | ||
sub test_recv { | ||
set req.http.VARS = ""; | ||
set req.http.VARS:VALUE = ""; | ||
set req.http.VARS:VALUE2 = ""; | ||
assert.equal(req.http.VARS, "VALUE, VALUE2"); | ||
} | ||
|
||
// @scope: recv | ||
// @suite: UNSET VARS ALL VALUE | ||
sub test_recv { | ||
set req.http.VARS = ""; | ||
set req.http.VARS:VALUE = "V"; | ||
unset req.http.VARS:VALUE; | ||
assert.is_notset(req.http.VARS); | ||
} | ||
|
||
// @scope: recv | ||
// @suite: UNSET VARS VALUE | ||
sub test_recv { | ||
set req.http.VARS = ""; | ||
set req.http.VARS:VALUE = "V"; | ||
set req.http.VARS:VALUE2 = "V2"; | ||
unset req.http.VARS:VALUE; | ||
assert.equal(req.http.VARS, "VALUE2=V2"); | ||
} | ||
|
||
// @scope: recv | ||
// @suite: OVERRIDE VARS VALUE | ||
sub test_recv { | ||
set req.http.VARS = ""; | ||
set req.http.VARS:VALUE = "V"; | ||
set req.http.VARS:VALUE = "O"; | ||
assert.equal(req.http.VARS, "VALUE=O"); | ||
} | ||
|
||
// @scope: recv | ||
// @suite: SET NULL VALUE | ||
sub test_recv { | ||
set req.http.VARS = ""; | ||
set req.http.VARS:VALUE = "V"; | ||
set req.http.VARS:VALUE = req.http.NULL; | ||
assert.equal(req.http.VARS, "VALUE"); | ||
} |
File renamed without changes.
File renamed without changes.
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.
Started looking through the PR this morning and the test assertions in this file stood out to me.
For example in this test:
What seemed odd to me was the fact that
assert.equal(req.http.MESSAGE, "(null)");
was passing when the header is unset. A condition likereq.http.MESSAGE == "(null)"
in an if statement for example should evaluate tofalse
. Soassert.equal
should seemingly also reject this case.Put together a fiddle that reproduces the sequence of
set
s from the test and inspecting the results.https://fiddle.fastly.dev/fiddle/d1c67281
The log output of that fiddle is
Both the VALUE and MESSAGE headers are "not set" and don't equal "(null)" in the context of an if statement condition. But what I found interesting is that the logged value is "(null)". That fact started a whole other path of looking into the behavior of all this and I ran out of time to be able to get back to reviewing the PR.
I started putting together another fiddle with as many permutations of usage of unset header and local string variables I could think of to use as a basis for comparing the falco not set string behavior with what Fastly is doing. Will share that when I have some time to finish it and will get back to reading through more of the PR soon.
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.
Yes, you are right - this looks strange to us but it simulates Fastly's behavior.
The
NotSet
string evaluation depends on the context, sometimes empty string, and sometimes "(null)", and unfortunately Fastly VCL developer also could not grab all cases that theNotSet
string could evaluate as "(null)".However, I'd understand the cases following:
log
,synthetic
, andsynthetic_base64
statements, message string includes NotSet will evaluate as "(null)"STRING
local variable likevar.SomeString
will evaluate asempty string
NotSet
string will be evaluated asfalsy
and any comparison operation should be treated like NULL.Probably there are more cases where the
NotSet
string is evaluated as "(null)" hence this PR includes the features that I only understand.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.
Didn't see this when writing up the comment with the test case fiddle/tests yesterday. I had missed the
synthetic
statements when thinking through various places where not set values would need to be considered.You're right
synthetic
does behave like thelog
statement and always expands not set values to(null)
.I'm not seeing the
(null)
behavior withsynthetic.base64
though. The response body in a fiddle withsynthetic.base64 req.http.unset
seems to be empty. Likewise doing a string concat expression with that statementsynthetic.base64 req.http.unset + "aGkK"
results in the bodyhi
without the(null)
expansion for the unset header.