Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ explorer/node_modules
explorer/dist
.idea
dist/*
assets/bindata.go
assets/bindata.go
.DS_Store
5 changes: 5 additions & 0 deletions commands/server/cli_app.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ func ConfigureServer(l *goapp.Lifecycle, conf *config.ServerConfig) {
Manager: app.Get("gonode.manager").(*core.PgNodeManager),
},
"core.raw": &raw.RawViewHandler{},
"media.image": &media.MediaViewHandler{
Vault: app.Get("gonode.vault.fs").(*vault.Vault),
MaxWidth: conf.Media.Image.MaxWidth,
AllowedWidths: conf.Media.Image.AllowedWidths,
},
}
})

Expand Down
1 change: 1 addition & 0 deletions docs/modules/guard.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ Guard
=====

Introduction
------------

Guard plugin handle request authentification. The modules comes with a dedicated middleware and request authenticators.
For now there is only 2 authenticators implemented:
Expand Down
86 changes: 86 additions & 0 deletions docs/modules/media.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
Media
=====

Introduction
------------

Media stores information about a media, for now only image and youtube videos are supported.

Image Type
----------

The image type provides the current fields:

Meta:

- ``Width``
- ``Height``
- ``Size``
- ``ContentType``
- ``Length``
- ``Exif``: not used yet
- ``Hash``: not used yet
- ``SourceStatus``: SourceUrl processing status
- ``SourceError``: SourceUrl processing result on error

Data:

- ``Reference``: contextual information about the media
- ``Name``: image name
- ``SourceUrl``: can be used to provided an url to retrieve the media

You can retrieve the binary through an api call by adding the ``?raw=1`` into the query string. The prism handler can
also be used, this entry point will provide crop and resize option.

- ``http://localhost:2405/prism/bcb537ab-b349-4b3d-87e2-e43e17519af7`` => get the original image
- ``http://localhost:2405/prism/bcb537ab-b349-4b3d-87e2-e43e17519af7?mr=250`` => resize the media with the provided width
- ``http://localhost:2405/prism/bcb537ab-b349-4b3d-87e2-e43e17519af7?mf=200,200`` => crop the media using a 200x200 square from
the center of the image.
- ``http://localhost:2405/prism/bcb537ab-b349-4b3d-87e2-e43e17519af7?mf=200,200,50,50`` => crop the media using a 200x200 square from
the 50x50 top left corner.

The image resize and crop only works with: ``jpg``, ``png`` and ``jpg`` files.

YouTube Type
------------

The YouTube type provided the following fields:

Meta (from youtube metadata)

- ``Type``
- ``Html``
- ``Width``
- ``Height``
- ``Version``
- ``Title``
- ``ProviderName``
- ``AuthorName``
- ``AuthorUrl``
- ``ProviderUrl``
- ``ThumbnailUrl``
- ``ThumbnailWidth``
- ``ThumbnailHeight``

Data:

- ``Vid``: The video id
- ``Status``: processing status
- ``Error``: processing error

The downloaded thumbnail will become a media type.

Configuration
-------------

```toml
[media]
[media.image]
allowed_widths = [100, 200]
max_width = 300
```

- ``allowed_widths``: slice of valid widths, if empty all widths are possible
- ``max_width``: max allows width, if empty and ``allowed_width`` is empty then all widths are possible.

*To avoid any issues, those settings must be set and a cache layer configured*
16 changes: 16 additions & 0 deletions modules/config/config_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,15 @@ type ServerSecurity struct {
} `toml:"cors"`
}

type ServerMediaImage struct {
AllowedWidths []uint `toml:"allowed_widths"`
MaxWidth uint `toml:"max_width"`
}

type ServerMedia struct {
Image *ServerMediaImage `toml:"image"`
}

type ServerDatabase struct {
Name string `toml:"name"`
DSN string `toml:"dsn"`
Expand Down Expand Up @@ -78,6 +87,7 @@ type ServerConfig struct {
Security *ServerSecurity `toml:"security"`
Search *ServerSearch `toml:"search"`
BinData *ServerBinData `toml:"bindata"`
Media *ServerMedia `toml:"media"`
}

func NewServerConfig() *ServerConfig {
Expand All @@ -93,5 +103,11 @@ func NewServerConfig() *ServerConfig {
Assets: make(map[string]*ServerBinDataAsset, 0),
// Templates: make([]string, 0),
},
Media: &ServerMedia{
Image: &ServerMediaImage{
MaxWidth: uint(1024),
// AllowedWidths: make([]uint, 0),
},
},
}
}
8 changes: 8 additions & 0 deletions modules/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ key = "ZeSecretKey0oo"
public = "/explorer"
private = "github.com/rande/gonode/explorer/dist"

[media]
[media.image]
allowed_widths = [100, 200]
max_width = 300
`, config)

assert.NoError(t, err)
Expand Down Expand Up @@ -103,6 +107,10 @@ key = "ZeSecretKey0oo"
assert.Equal(t, "/var/go", config.BinData.BasePath)
assert.Equal(t, []string{"/path/post/templates", "/path/media/templates"}, config.BinData.Templates)

// test media
assert.Equal(t, uint(300), config.Media.Image.MaxWidth)
assert.Equal(t, []uint{100, 200}, config.Media.Image.AllowedWidths)

// debug
config.Guard.Jwt.Login.Path = `^\/nodes\/(.*)$`

Expand Down
40 changes: 40 additions & 0 deletions modules/helper/reader.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright © 2014-2015 Thomas Rabaix <thomas.rabaix@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

package helper

import (
"io"
)

type PartialReader struct {
Reader io.ReadCloser
Size int
Data []byte
Len int
}

func (r *PartialReader) Read(p []byte) (n int, err error) {
n, err = r.Reader.Read(p)

toRead := r.Size - len(r.Data)

if toRead > 0 {
if n < toRead {
toRead = n
}

dst := make([]byte, toRead)
n := copy(dst, p)

r.Data = append(r.Data, dst[0:n]...)
}

return
}

func (r *PartialReader) Close() error {
return r.Reader.Close()
}
59 changes: 59 additions & 0 deletions modules/helper/reader_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright © 2014-2015 Thomas Rabaix <thomas.rabaix@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

package helper

import (
"github.com/stretchr/testify/assert"
"io/ioutil"
"os"
"testing"
)

func Test_Parial_Reader_Incomplet_Data(t *testing.T) {

f, _ := ioutil.TempFile(os.TempDir(), "gonode_test")
f.Write([]byte("hello world"))
f.Seek(0, 0)

defer f.Close()

r := PartialReader{
Reader: f,
Size: 20,
}

data := make([]byte, 50)

n, err := r.Read(data)

assert.NoError(t, err)
assert.Equal(t, 11, n)
assert.Equal(t, []byte("hello world"), data[:n])
assert.Equal(t, []byte("hello world"), r.Data)
}

func Test_Parial_Reader_Complet_Data(t *testing.T) {

f, _ := ioutil.TempFile(os.TempDir(), "gonode_test")
f.Write([]byte("hello world"))
f.Seek(0, 0)

defer f.Close()

r := PartialReader{
Reader: f,
Size: 5,
}

data := make([]byte, 50)

n, err := r.Read(data)

assert.NoError(t, err)
assert.Equal(t, 11, n)
assert.Equal(t, []byte("hello world"), data[:n])
assert.Equal(t, []byte("hello"), r.Data)
}
11 changes: 9 additions & 2 deletions modules/media/media_image.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import (
"fmt"
"github.com/lib/pq"
"github.com/rande/gonode/core"
"github.com/rande/gonode/modules/helper"
"github.com/rande/gonode/modules/vault"
"io"
"net/http"
)

type ExifMeta map[string]string
Expand Down Expand Up @@ -165,13 +167,18 @@ func (l *ImageDownloadListener) Handle(notification *pq.Notification, m core.Nod

vaultmeta := core.GetVaultMetadata(node)

_, err = l.Vault.Put(node.UniqueId(), vaultmeta, resp.Body)
r := &helper.PartialReader{
Reader: resp.Body,
Size: 500,
}

_, err = l.Vault.Put(node.UniqueId(), vaultmeta, r)

if err != nil {
return core.PubSubListenContinue, err
}

meta.ContentType = "application/octet-stream"
meta.ContentType = http.DetectContentType(r.Data)
meta.SourceStatus = core.ProcessStatusDone

m.Save(node, false)
Expand Down
Loading