Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
caddy
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Łukasz Nowak
caddy
Commits
7b29568e
Commit
7b29568e
authored
9 years ago
by
Abiola Ibrahim
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Code cleanups.
Fix more race conditions.
parent
e240cd5b
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
135 additions
and
40 deletions
+135
-40
middleware/markdown/markdown.go
middleware/markdown/markdown.go
+10
-8
middleware/markdown/markdown_test.go
middleware/markdown/markdown_test.go
+47
-12
middleware/markdown/page.go
middleware/markdown/page.go
+76
-18
middleware/markdown/process.go
middleware/markdown/process.go
+2
-2
No files found.
middleware/markdown/markdown.go
View file @
7b29568e
...
...
@@ -4,13 +4,14 @@ package markdown
import
(
"io/ioutil"
"log"
"net/http"
"os"
"strings"
"sync"
"github.com/mholt/caddy/middleware"
"github.com/russross/blackfriday"
// "log"
)
// Markdown implements a layer of middleware that serves
...
...
@@ -70,11 +71,14 @@ type Config struct {
// Directory to store static files
StaticDir
string
sync
.
RWMutex
}
// ServeHTTP implements the http.Handler interface.
func
(
md
Markdown
)
ServeHTTP
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
(
int
,
error
)
{
for
_
,
m
:=
range
md
.
Configs
{
for
i
:=
range
md
.
Configs
{
m
:=
&
md
.
Configs
[
i
]
if
!
middleware
.
Path
(
r
.
URL
.
Path
)
.
Matches
(
m
.
PathScope
)
{
continue
}
...
...
@@ -120,11 +124,9 @@ func (md Markdown) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error
if
m
.
StaticDir
!=
""
{
// Markdown modified or new. Update links.
// go func() {
// if err := GenerateLinks(md, &md.Configs[i]); err != nil {
// log.Println(err)
// }
// }()
if
err
:=
GenerateLinks
(
md
,
m
);
err
!=
nil
{
log
.
Println
(
err
)
}
}
body
,
err
:=
ioutil
.
ReadAll
(
f
)
...
...
@@ -137,7 +139,7 @@ func (md Markdown) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error
Req
:
r
,
URL
:
r
.
URL
,
}
html
,
err
:=
md
.
Process
(
m
,
fpath
,
body
,
ctx
)
html
,
err
:=
md
.
Process
(
*
m
,
fpath
,
body
,
ctx
)
if
err
!=
nil
{
return
http
.
StatusInternalServerError
,
err
}
...
...
This diff is collapsed.
Click to expand it.
middleware/markdown/markdown_test.go
View file @
7b29568e
...
...
@@ -4,6 +4,7 @@ import (
"net/http"
"net/http/httptest"
"strings"
"sync"
"testing"
"github.com/mholt/caddy/middleware"
...
...
@@ -18,20 +19,24 @@ func TestMarkdown(t *testing.T) {
FileSys
:
http
.
Dir
(
"./testdata"
),
Configs
:
[]
Config
{
Config
{
Renderer
:
blackfriday
.
HtmlRenderer
(
0
,
""
,
""
),
PathScope
:
"/blog"
,
Extensions
:
[]
string
{
".md"
},
Styles
:
[]
string
{},
Scripts
:
[]
string
{},
Templates
:
templates
,
Renderer
:
blackfriday
.
HtmlRenderer
(
0
,
""
,
""
),
PathScope
:
"/blog"
,
Extensions
:
[]
string
{
".md"
},
Styles
:
[]
string
{},
Scripts
:
[]
string
{},
Templates
:
templates
,
StaticDir
:
DefaultStaticDir
,
StaticFiles
:
make
(
map
[
string
]
string
),
},
Config
{
Renderer
:
blackfriday
.
HtmlRenderer
(
0
,
""
,
""
),
PathScope
:
"/log"
,
Extensions
:
[]
string
{
".md"
},
Styles
:
[]
string
{
"/resources/css/log.css"
,
"/resources/css/default.css"
},
Scripts
:
[]
string
{
"/resources/js/log.js"
,
"/resources/js/default.js"
},
Templates
:
make
(
map
[
string
]
string
),
Renderer
:
blackfriday
.
HtmlRenderer
(
0
,
""
,
""
),
PathScope
:
"/log"
,
Extensions
:
[]
string
{
".md"
},
Styles
:
[]
string
{
"/resources/css/log.css"
,
"/resources/css/default.css"
},
Scripts
:
[]
string
{
"/resources/js/log.js"
,
"/resources/js/default.js"
},
Templates
:
make
(
map
[
string
]
string
),
StaticDir
:
DefaultStaticDir
,
StaticFiles
:
make
(
map
[
string
]
string
),
},
},
IndexFiles
:
[]
string
{
"index.html"
},
...
...
@@ -123,4 +128,34 @@ func getTrue() bool {
if
respBody
!=
expectedBody
{
t
.
Fatalf
(
"Expected body: %v got: %v"
,
expectedBody
,
respBody
)
}
expectedLinks
:=
[]
string
{
"/blog/test.md"
,
"/log/test.md"
,
}
for
i
,
c
:=
range
md
.
Configs
{
if
c
.
Links
[
0
]
.
Url
!=
expectedLinks
[
i
]
{
t
.
Fatalf
(
"Expected %v got %v"
,
expectedLinks
[
i
],
c
.
Links
[
0
]
.
Url
)
}
}
// attempt to trigger race condition
var
w
sync
.
WaitGroup
f
:=
func
()
{
req
,
err
:=
http
.
NewRequest
(
"GET"
,
"/log/test.md"
,
nil
)
if
err
!=
nil
{
t
.
Fatalf
(
"Could not create HTTP request: %v"
,
err
)
}
rec
:=
httptest
.
NewRecorder
()
md
.
ServeHTTP
(
rec
,
req
)
w
.
Done
()
}
for
i
:=
0
;
i
<
5
;
i
++
{
w
.
Add
(
1
)
go
f
()
}
w
.
Wait
()
}
This diff is collapsed.
Click to expand it.
middleware/markdown/page.go
View file @
7b29568e
...
...
@@ -12,17 +12,15 @@ import (
"github.com/russross/blackfriday"
)
var
(
pagesMutex
sync
.
RWMutex
linksGenerating
bool
)
const
(
// Date format YYYY-MM-DD HH:MM:SS
timeLayout
=
`2006-01-02 15:04:05`
// Length of page summary.
summaryLen
=
150
)
// Page represents a statically generated markdown page.
// Page
Link
represents a statically generated markdown page.
type
PageLink
struct
{
Title
string
Summary
string
...
...
@@ -30,25 +28,51 @@ type PageLink struct {
Url
string
}
// pageLinkSorter sort PageLink by newest date to oldest.
// pageLinkSorter sort
s
PageLink by newest date to oldest.
type
pageLinkSorter
[]
PageLink
func
(
p
pageLinkSorter
)
Len
()
int
{
return
len
(
p
)
}
func
(
p
pageLinkSorter
)
Swap
(
i
,
j
int
)
{
p
[
i
],
p
[
j
]
=
p
[
j
],
p
[
i
]
}
func
(
p
pageLinkSorter
)
Less
(
i
,
j
int
)
bool
{
return
p
[
i
]
.
Date
.
After
(
p
[
j
]
.
Date
)
}
func
GenerateLinks
(
md
Markdown
,
cfg
*
Config
)
error
{
if
linksGenerating
{
return
nil
type
linkGen
struct
{
generating
bool
waiters
int
lastErr
error
sync
.
RWMutex
sync
.
WaitGroup
}
func
(
l
*
linkGen
)
addWaiter
()
{
l
.
WaitGroup
.
Add
(
1
)
l
.
waiters
++
}
func
(
l
*
linkGen
)
discardWaiters
()
{
l
.
Lock
()
defer
l
.
Unlock
()
for
i
:=
0
;
i
<
l
.
waiters
;
i
++
{
l
.
Done
()
}
}
func
(
l
*
linkGen
)
started
()
bool
{
l
.
RLock
()
defer
l
.
RUnlock
()
return
l
.
generating
}
pagesMutex
.
Lock
()
linksGenerating
=
true
func
(
l
*
linkGen
)
generateLinks
(
md
Markdown
,
cfg
*
Config
)
{
l
.
Lock
()
l
.
generating
=
true
l
.
Unlock
()
fp
:=
filepath
.
Join
(
md
.
Root
,
cfg
.
PathScope
)
cfg
.
Links
=
[]
PageLink
{}
err
:=
filepath
.
Walk
(
fp
,
func
(
path
string
,
info
os
.
FileInfo
,
err
error
)
error
{
cfg
.
Lock
()
l
.
lastErr
=
filepath
.
Walk
(
fp
,
func
(
path
string
,
info
os
.
FileInfo
,
err
error
)
error
{
for
_
,
ext
:=
range
cfg
.
Extensions
{
if
!
info
.
IsDir
()
&&
strings
.
HasSuffix
(
info
.
Name
(),
ext
)
{
// Load the file
...
...
@@ -92,12 +116,46 @@ func GenerateLinks(md Markdown, cfg *Config) error {
}
}
// sort by newest date
sort
.
Sort
(
pageLinkSorter
(
cfg
.
Links
))
return
nil
})
linksGenerating
=
false
pagesMutex
.
Unlock
()
return
err
// sort by newest date
sort
.
Sort
(
pageLinkSorter
(
cfg
.
Links
))
cfg
.
Unlock
()
l
.
Lock
()
l
.
generating
=
false
l
.
Unlock
()
}
type
linkGenerator
struct
{
gens
map
[
*
Config
]
*
linkGen
sync
.
Mutex
}
var
generator
=
linkGenerator
{
gens
:
make
(
map
[
*
Config
]
*
linkGen
)}
// GenerateLinks generates links to all markdown files ordered by newest date.
// This blocks until link generation is done. When called by multiple goroutines,
// the first caller starts the generation and others only wait.
func
GenerateLinks
(
md
Markdown
,
cfg
*
Config
)
error
{
generator
.
Lock
()
// if link generator exists for config and running, wait.
if
g
,
ok
:=
generator
.
gens
[
cfg
];
ok
{
if
g
.
started
()
{
g
.
addWaiter
()
generator
.
Unlock
()
g
.
Wait
()
return
g
.
lastErr
}
}
g
:=
&
linkGen
{}
generator
.
gens
[
cfg
]
=
g
generator
.
Unlock
()
g
.
generateLinks
(
md
,
cfg
)
g
.
discardWaiters
()
return
g
.
lastErr
}
This diff is collapsed.
Click to expand it.
middleware/markdown/process.go
View file @
7b29568e
...
...
@@ -101,9 +101,9 @@ func (md Markdown) processTemplate(c Config, requestPath string, tmpl []byte, me
Links
:
c
.
Links
,
}
pagesMutex
.
RLock
()
c
.
RLock
()
err
=
t
.
Execute
(
b
,
mdData
)
pagesMutex
.
RUnlock
()
c
.
RUnlock
()
if
err
!=
nil
{
return
nil
,
err
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment