Skip to content

Commit d57af3c

Browse files
committed
Merge branch 'master' into issue/40
2 parents f82ea00 + f9fa948 commit d57af3c

File tree

12 files changed

+221
-18
lines changed

12 files changed

+221
-18
lines changed

.github/ISSUE_TEMPLATE/bug_report.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---
2+
name: Bug report
3+
about: Create a report to help us improve
4+
5+
---
6+
7+
**Describe the bug**
8+
A clear and concise description of what the bug is.
9+
10+
**To Reproduce**
11+
Steps to reproduce the behavior:
12+
1. Start container with x/y arguments
13+
2. View logs on '....'
14+
3. See error
15+
16+
**Expected behavior**
17+
A clear and concise description of what you expected to happen.
18+
19+
**Your environment**
20+
* Version of the repo - a specific commit or tag
21+
* Version of the container used (if downloaded from Docker Hub or Github)
22+
* S3 backend implementation you are using (AWS, Ceph, NetApp StorageGrid, etc)
23+
* How you are deploying Docker/Stand-alone, etc
24+
* NGINX type (OSS/Plus)
25+
* Authentication method (IAM, IAM with Fargate, IAM with K8S, AWS Credentials, etc)
26+
27+
**Additional context**
28+
Add any other context about the problem here. Any log files you want to share.
29+
30+
**Sensitive Information**
31+
Be sure to redact any sensitive information such as your AWS authentication keys.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
name: Feature request
3+
about: Suggest an idea for this project
4+
5+
---
6+
7+
**Is your feature request related to a problem? Please describe.**
8+
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
9+
10+
**Describe the solution you'd like**
11+
A clear and concise description of what you want to happen.
12+
13+
**Describe alternatives you've considered**
14+
A clear and concise description of any alternative solutions or features you've considered.
15+
16+
**Additional context**
17+
Add any other context or screenshots about the feature request here.

common/etc/nginx/include/listing.xsl

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?xml version="1.0"?>
2-
<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
2+
<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:str="http://exslt.org/strings" extension-element-prefixes="str">
33
<xsl:output method="html" encoding="utf-8" indent="yes"/>
4+
<xsl:strip-space elements="*" />
45

56
<xsl:template match="/">
67
<xsl:choose>
@@ -81,7 +82,7 @@
8182
select="substring-after(text(), $globalPrefix)"/>
8283
<tr>
8384
<td>
84-
<a href="/{text()}">
85+
<a><xsl:attribute name="href">/<xsl:call-template name="encode-uri"><xsl:with-param name="uri" select="text()"/></xsl:call-template>/</xsl:attribute>
8586
<xsl:value-of select="$dirName"/>
8687
</a>
8788
</td>
@@ -103,7 +104,8 @@
103104
<xsl:variable name="size" select="*[local-name()='Size']/text()"/>
104105
<tr>
105106
<td>
106-
<a href="/{$key}">
107+
<a>
108+
<xsl:attribute name="href">/<xsl:call-template name="encode-uri"><xsl:with-param name="uri" select="$key"/></xsl:call-template></xsl:attribute>
107109
<xsl:value-of select="$fileName"/>
108110
</a>
109111
</td>
@@ -116,4 +118,21 @@
116118
</tr>
117119
</xsl:if>
118120
</xsl:template>
121+
<!-- This template escapes the URI such that symbols or unicode characters are
122+
encoded so that they form a valid link that NGINX can parse -->
123+
<xsl:template name="encode-uri">
124+
<xsl:param name="uri"/>
125+
<xsl:for-each select="str:split($uri, '/')">
126+
<xsl:variable name="encoded" select="str:encode-uri(., 'true', 'UTF-8')" />
127+
<xsl:variable name="more-encoded" select="
128+
str:replace(
129+
str:replace(
130+
str:replace(
131+
str:replace(
132+
str:replace($encoded, '@', '%40'), '(', '%28'),
133+
')', '%29'),
134+
'!', '%21'),
135+
'*', '%2A')" />
136+
<xsl:value-of select="$more-encoded" /><xsl:if test="position() != last()">/</xsl:if></xsl:for-each>
137+
</xsl:template>
119138
</xsl:stylesheet>

common/etc/nginx/include/s3gateway.js

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -354,13 +354,14 @@ function s3uri(r) {
354354
if (queryParams.length > 0) {
355355
path = basePath + '?' + queryParams;
356356
} else {
357-
path = basePath + uriPath;
357+
path = _escapeURIPath(basePath + uriPath);
358358
}
359359
} else {
360+
// This is a path that will resolve to an index page
360361
if (provide_index_page && _isDirectory(uriPath) ) {
361-
uriPath += INDEX_PAGE;
362+
uriPath += INDEX_PAGE;
362363
}
363-
path = basePath + uriPath;
364+
path = _escapeURIPath(basePath + uriPath);
364365
}
365366

366367
_debug_log(r, 'S3 Request URI: ' + r.method + ' ' + path);
@@ -392,7 +393,7 @@ function _s3DirQueryParams(uriPath, method) {
392393
let decodedUriPath = decodeURIComponent(uriPath);
393394
let without_leading_slash = decodedUriPath.charAt(0) === '/' ?
394395
decodedUriPath.substring(1, decodedUriPath.length) : decodedUriPath;
395-
path += '&prefix=' + encodeURIComponent(without_leading_slash);
396+
path += '&prefix=' + _encodeURIComponent(without_leading_slash);
396397
}
397398

398399
return path;
@@ -419,7 +420,7 @@ function redirectToS3(r) {
419420
if (isDirectoryListing && r.method === 'GET') {
420421
r.internalRedirect("@s3Listing");
421422
} else if ( provide_index_page == true ) {
422-
r.internalRedirect("@s3");
423+
r.internalRedirect("@s3");
423424
} else if ( !allow_listing && !provide_index_page && uriPath == "/" ) {
424425
r.internalRedirect("@error404");
425426
} else {
@@ -569,8 +570,9 @@ function _buildSignatureV4(r, amzDatetime, eightDigitDate, creds, bucket, region
569570
uri = '/';
570571
}
571572
} else {
572-
uri = _escapeURIPath(s3uri(r));
573+
uri = s3uri(r);
573574
}
575+
574576
var canonicalRequest = _buildCanonicalRequest(method, uri, queryParams, host, amzDatetime, creds.sessionToken);
575577

576578
_debug_log(r, 'AWS v4 Auth Canonical Request: [' + canonicalRequest + ']');
@@ -781,6 +783,19 @@ function _padWithLeadingZeros(num, size) {
781783
return s.substr(s.length-size);
782784
}
783785

786+
/**
787+
* Adds additional encoding to a URI component
788+
*
789+
* @param string {string} string to encode
790+
* @returns {string} an encoded string
791+
* @private
792+
*/
793+
function _encodeURIComponent(string) {
794+
return encodeURIComponent(string)
795+
.replace(/[!*'()]/g, (c) =>
796+
`%${c.charCodeAt(0).toString(16).toUpperCase()}`);
797+
}
798+
784799
/**
785800
* Escapes the path portion of a URI without escaping the path separator
786801
* characters (/).
@@ -795,7 +810,7 @@ function _escapeURIPath(uri) {
795810
let components = [];
796811

797812
decodedUri.split('/').forEach(function (item, i) {
798-
components[i] = encodeURIComponent(item);
813+
components[i] = _encodeURIComponent(item);
799814
});
800815

801816
return components.join('/');
@@ -1105,6 +1120,7 @@ export default {
11051120
// These functions do not need to be exposed, but they are exposed so that
11061121
// unit tests can run against them.
11071122
_padWithLeadingZeros,
1123+
_encodeURIComponent,
11081124
_eightDigitDate,
11091125
_amzDatetime,
11101126
_splitCachedValues,

docs/development.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ In the [examples/ directory](/examples), there are `Dockerfile` examples that
66
show how to extend the base functionality of the NGINX S3 Gateway by adding
77
additional modules.
88

9-
* [Enabling Brotli Compression in Docker](examples/brotli-compression)
10-
* [Enabling GZip Compression in Docker](examples/gzip-compression)
11-
* [Installing Modsecurity in Docker](examples/modsecurity)
9+
* [Enabling Brotli Compression in Docker](/examples/brotli-compression)
10+
* [Enabling GZip Compression in Docker](/examples/gzip-compression)
11+
* [Installing Modsecurity in Docker](/examples/modsecurity)
1212

1313
## Testing
1414

test/data/bucket-1/a/%@!*()=$#^&|.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
We are but selling water next to a river.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
"Where the is not one thing, what then?"
2+
"Throw it away!"
3+
"With not one thing, what there is to throw away?"
4+
"Then carry it off!"

test/data/bucket-1/a/plus+plus.txt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
代悲白頭翁   Lament for the White-Haired Old Man
2+
洛陽城東桃李花 In the east of Luoyang City, Peach blossoms abound
3+
飛來飛去落誰家 Their petals float around, coming and going, to whose house will they fall?
4+
洛陽女児惜顔色 Girls in Luoyang cherish their complexion
5+
行逢落花長歎息 They breathe a deep sigh upon seeing the petals fall
6+
今年花落顔色改 This year the petals fall and their complexion changes
7+
明年花開復誰在 Who will be there when the flowers bloom next year?
8+
已見松柏摧為薪 I've seen the pines and cypresses destroyed and turned into firewood
9+
更聞桑田変成海 I hear that the mulberry fields have fallen into the sea
10+
古人無復洛城東 The people of old never came back to the east of Luoyang City
11+
今人還對落花風 The people of today likewise face the falling flowers in the wind
12+
年年歳歳花相似 Year after year, flowers look alike
13+
歳歳年年人不同 Year after year, the people are not the same
14+
寄言全盛紅顔子 I want you to get this message, my child, you are in your prime, with a rosy complexion
15+
應憐半死白頭翁 Take pity on the half-dead white-haired old man
16+
此翁白頭真可憐 You really must take pity on this white-haired old man
17+
伊昔紅顔美少年 For once upon a time, I used to be a red-faced handsome young man
18+
公子王孫芳樹下 A child of noble birth under a fragrant tree
19+
清歌妙舞落花前 Singing and dancing in front of the falling petals
20+
光禄池臺開錦繍 At the platform before the mirror pond, beautiful autumn leaves opening all around
21+
将軍楼閣畫神仙 The general’s pavilion is painted with gods and goddesses
22+
一朝臥病無相識 Once I was sick and no one knew me
23+
三春行楽在誰邉 Who will be at the shore for the spring outing?
24+
宛轉蛾眉能幾時 For how long will the moths gracefully turn about?
25+
須臾鶴髪亂如絲 The crane’s feathers are like tangled threads for just a moment
26+
但看古来歌舞地 Yet, look at the ancient places of song and dance
27+
惟有黄昏鳥雀悲 Only in twilight, do the birds lament
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
What name do you use to call out to the emptiness?

test/data/bucket-1/b/c/'(1).txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
In the midst of movement and chaos, keep stillness inside of you.

0 commit comments

Comments
 (0)