Основное веб -приложение MVC в Go
Этот проект демонстрирует, как структурировать и создать веб -сайт, используя язык GO без структуры. Есть статья в блоге, которую вы можете прочитать по адресу http://www.josephspurrier.com/go-web-app-example/. Есть полное приложение, которое я построил с более ранней версией проекта по адресу https://github.com/verifiedninja/webapp. Есть версия API этого проекта по адресу https://github.com/josephspurrier/gowebapi.
Чтобы загрузить, запустите следующую команду:
go get github.com/josephspurrier/gowebapp
Если вы находитесь в Go 1.5, вам нужно установить Govendorexperiment на 1. Если вы находитесь в Go 1.4 или раньше, код не будет работать, потому что он использует папку поставщика.
Файл gowebapp.db будет создан после начала приложения.
Стройте и запустите из корневого каталога. Откройте свой веб -браузер по адресу: http: // localhost. Вы должны увидеть страницу приветствия.
Перейдите на страницу входа в систему, а затем на страницу регистрации. Создайте нового пользователя, и вы сможете входить в систему. Вот и все.
Начните mongodb.
Откройте config/config.json и отредактируйте раздел базы данных, чтобы информация об подключении соответствовала вашему экземпляру MongoDB. Также изменение типа с болта на MongoDB.
Стройте и запустите из корневого каталога. Откройте свой веб -браузер по адресу: http: // localhost. Вы должны увидеть страницу приветствия.
Перейдите на страницу входа в систему, а затем на страницу регистрации. Создайте нового пользователя, и вы сможете входить в систему. Вот и все.
Запустите MySQL и импортировать config/mysql.sql для создания базы данных и таблиц.
Откройте config/config.json и отредактируйте раздел базы данных, чтобы информация об подключении соответствовала вашему экземпляру MySQL. Кроме того, измените тип с болта на MySQL.
Стройте и запустите из корневого каталога. Откройте свой веб -браузер по адресу: http: // localhost. Вы должны увидеть страницу приветствия.
Перейдите на страницу входа в систему, а затем на страницу регистрации. Создайте нового пользователя, и вы сможете входить в систему. Вот и все.
В веб -приложении есть общедоступная домашняя страница, аутентифицированная домашняя страница, страница входа в систему, страницу регистрации, о странице и простой блокнот, чтобы продемонстрировать операции CRUD.
Входной точкой для веб -приложения является gowebapp.go. Файл загружает настройки приложения, запускает сеанс, подключается к базе данных, устанавливает шаблоны, загружает маршруты, прикрепляет промежуточное программное обеспечение и запускает веб -сервер.
Передняя часть создана с использованием начальной загрузки с несколькими небольшими изменениями в шрифтах и интервале. Флэш -сообщения настроены так, чтобы они отображались в правом нижнем углу экрана.
Все сообщения об ошибке и предупреждения должны отображаться либо для пользователя, либо в консоли. Информационные сообщения отображаются пользователю через флэш -сообщения, которые исчезают через 4 секунды. Флэш -сообщения контролируются JavaScript в статической папке.
Недавно структура папок изменилась. Посмотрев на все вилки и повторно используя свой проект в разных местах, я решил переместить код GO в папку приложений в папке поставщика , чтобы путь GitHub не был завален на протяжении многих импортов. Я не хотел использовать относительные пути, поэтому папка поставщика казалась лучшим вариантом.
Проект организован в следующие папки:
config - application settings and database schema
static - location of statically served files like CSS and JS
template - HTML templates
vendor/app/controller - page logic organized by HTTP methods (GET, POST)
vendor/app/shared - packages for templates, MySQL, cryptography, sessions, and json
vendor/app/model - database queries
vendor/app/route - route information and middleware
Есть несколько внешних пакетов:
github.com/gorilla/context - registry for global request variables
github.com/gorilla/sessions - cookie and filesystem sessions
github.com/go-sql-driver/mysql - MySQL driver
github.com/haisum/recaptcha - Google reCAPTCHA support
github.com/jmoiron/sqlx - MySQL general purpose extensions
github.com/josephspurrier/csrfbanana - CSRF protection for gorilla sessions
github.com/julienschmidt/httprouter - high performance HTTP request router
github.com/justinas/alice - middleware chaining
github.com/mattn/go-sqlite3 - SQLite driver
golang.org/x/crypto/bcrypt - password hashing algorithm
Шаблоны организованы в папки под папкой шаблона :
about/about.tmpl - quick info about the app
index/anon.tmpl - public home page
index/auth.tmpl - home page once you login
login/login.tmpl - login page
notepad/create.tmpl - create note
notepad/read.tmpl - read a note
notepad/update.tmpl - update a note
partial/footer.tmpl - footer
partial/menu.tmpl - menu at the top of all the pages
register/register.tmpl - register page
base.tmpl - base template for all the pages
Есть несколько шаблонов, доступных для облегчения работы с шаблонами и статическими файлами:
<!-- CSS files with timestamps -->
{{CSS "static/css/normalize3.0.0.min.css"}}
parses to
< link rel =" stylesheet " type =" text/css " href =" /static/css/normalize3.0.0.min.css?1435528339 " />
<!-- JS files with timestamps -->
{{JS "static/js/jquery1.11.0.min.js"}}
parses to
< script type =" text/javascript " src =" /static/js/jquery1.11.0.min.js?1435528404 " > </ script >
<!-- Hyperlinks -->
{{LINK "register" "Create a new account."}}
parses to
< a href =" /register " > Create a new account. </ a >
<!-- Output an unescaped variable (not a safe idea, but I find it useful when troubleshooting) -->
{{.SomeVariable | NOESCAPE}}
<!-- Time format -->
{{.SomeTime | PRETTYTIME}}
parses to format
3:04 PM 01/02/2006Есть несколько переменных, которые вы можете использовать и в шаблонах:
<!-- Use AuthLevel=auth to determine if a user is logged in (if session.Values["id"] != nil) -->
{{if eq .AuthLevel "auth"}}
You are logged in.
{{else}}
You are not logged in.
{{end}}
<!-- Use BaseURI to print the base URL of the web app -->
< li > < a href =" {{.BaseURI}}about " > About </ a > </ li >
<!-- Use token to output the CSRF token in a form -->
< input type =" hidden " name =" token " value =" {{.token}} " >Также легко добавить код, специфичный для шаблона, перед закрытием и тегами:
<!-- Code is added before the closing </head> tag -->
{{define "head"}} < meta name =" robots " content =" noindex " > {{end}}
...
<!-- Code is added before the closing </body> tag -->
{{define "foot"}}{{JS "//www.google.com/recaptcha/api.js"}}{{end}}Вы можете запустить уведомление Flash с помощью JavaScript.
flashError ( "You must type in a username." ) ;
flashSuccess ( "Record created!" ) ;
flashNotice ( "There seems to be a piece missing." ) ;
flashWarning ( "Something does not seem right..." ) ; Файлы контроллера все совпадают с тем же именем пакета. Это сокращает количество пакетов, когда вы картируете маршруты. Это также заставляет вас использовать хорошее соглашение об именах для каждой из функций, чтобы вы знали, где находится каждая из функций и какой тип запроса HTTP они нанесены на карту.
Доступ к сеансу гориллы:
// Get the current session
sess := session . Instance ( r )
...
// Close the session after you are finished making changes
sess . Save ( r , w )Триггер 1 из 4 различных типов флэш -сообщений на загрузке следующей страницы (не требуется другой код):
sess . AddFlash (view. Flash { "Sorry, no brute force :-)" , view . FlashNotice })
sess . Save ( r , w ) // Ensure you save the session after making a change to itПроверка поля формы не пусты:
// Ensure a user submitted all the required form fields
if validate , missingField := view . Validate ( r , [] string { "email" , "password" }); ! validate {
sess . AddFlash (view. Flash { "Field missing: " + missingField , view . FlashError })
sess . Save ( r , w )
LoginGET ( w , r )
return
}Визуал шаблон:
// Create a new view
v := view . New ( r )
// Set the template name
v . Name = "login/login"
// Assign a variable that is accessible in the form
v . Vars [ "token" ] = csrfbanana . Token ( w , r , sess )
// Refill any form fields from a POST operation
view . Repopulate ([] string { "email" }, r . Form , v . Vars )
// Render the template
v . Render ( w )Вернуть флэш -сообщения во время запроса AJAX:
// Get session
sess := session . Instance ( r )
// Set the flash message
sess . AddFlash (view. Flash { "An error occurred on the server. Please try again later." , view . FlashError })
sess . Save ( r , w )
// Display the flash messages as JSON
v := view . New ( r )
v . SendFlashes ( w )Обрабатывать запрос базы данных:
// Get database result
result , err := model . UserByEmail ( email )
if err == sql . ErrNoRows {
// User does not exist
} else if err != nil {
// Display error message
} else if passhash . MatchString ( result . Password , password ) {
// Password matches!
} else {
// Password does not match
}Отправить электронное письмо:
// Email a user
err := email . SendEmail ( email . ReadConfig (). From , "This is the subject" , "This is the body!" )
if err != nil {
log . Println ( err )
sess . AddFlash (view. Flash { "An error occurred on the server. Please try again later." , view . FlashError })
sess . Save ( r , w )
return
}Проверить форму, если Google Recaptcha включена в конфигурации:
// Validate with Google reCAPTCHA
if ! recaptcha . Verified ( r ) {
sess . AddFlash (view. Flash { "reCAPTCHA invalid!" , view . FlashError })
sess . Save ( r , w )
RegisterGET ( w , r )
return
}Это хорошая идея, чтобы абстрагировать уровень базы данных, поэтому, если вам нужно вносить изменения, вам не нужно просматривать бизнес -логику, чтобы найти запросы. Все запросы хранятся в папке моделей.
Этот проект поддерживает Boltdb, MongoDB и MySQL. Все запросы хранятся в одних и тех же файлах, поэтому вы можете легко изменить базу данных, не изменяя ничего, кроме файла конфигурации.
Файлы user.go и note.go находятся в корне каталога модели и являются соответствием всех запросов для каждого типа базы данных. В моделях есть несколько хаков, чтобы заставить структуры работать со всеми поддерживаемыми базами данных.
Подключитесь к базе данных (только один раз в вашем приложении):
// Connect to database
database . Connect ( config . Database )Читайте из базы данных:
result := User {}
err := database . DB . Get ( & result , "SELECT id, password, status_id, first_name FROM user WHERE email = ? LIMIT 1" , email )
return result , errНапишите в базу данных:
_ , err := database . DB . Exec ( "INSERT INTO user (first_name, last_name, email, password) VALUES (?,?,?,?)" , firstName , lastName , email , password )
return err Есть несколько фрагментов промежуточного программного обеспечения. Пакет под названием Csrfbanana защищает от перекрестных запросов на подделку атаки и предотвращает двойные подчинения. Пакет HttProuterWrapper предоставляет вспомогательные функции, чтобы сделать функции совместимы с HttProuter. Пакет LogRequest будет регистрировать каждый запрос, сделанный на веб -сайте на консоли. Пакет PPROFHandler позволяет PPROF, поэтому он будет работать с HTTPROUTER. На Route.go все отдельные маршруты используют Алису, чтобы сделать цепочки очень простыми.
Чтобы сделать веб -приложение немного более гибким, вы можете вносить изменения в различные компоненты в одном месте через файл config.json. Если вы хотите добавить какие -либо из своих собственных настройки, вы можете добавить их в config.json и обновить структуры на gowebapp.go и отдельных файлах, чтобы вы могли ссылаться на них в своем коде. Это config.json:
{
"Database" : {
"Type" : " Bolt " ,
"Bolt" : {
"Path" : " gowebapp.db "
},
"MongoDB" : {
"URL" : " 127.0.0.1 " ,
"Database" : " gowebapp "
},
"MySQL" : {
"Username" : " root " ,
"Password" : " " ,
"Name" : " gowebapp " ,
"Hostname" : " 127.0.0.1 " ,
"Port" : 3306 ,
"Parameter" : " ?parseTime=true "
}
},
"Email" : {
"Username" : " " ,
"Password" : " " ,
"Hostname" : " " ,
"Port" : 25 ,
"From" : " "
},
"Recaptcha" : {
"Enabled" : false ,
"Secret" : " " ,
"SiteKey" : " "
},
"Server" : {
"Hostname" : " " ,
"UseHTTP" : true ,
"UseHTTPS" : false ,
"HTTPPort" : 80 ,
"HTTPSPort" : 443 ,
"CertFile" : " tls/server.crt " ,
"KeyFile" : " tls/server.key "
},
"Session" : {
"SecretKey" : " @r4B?EThaSEh_drudR7P_hub=s#s2Pah " ,
"Name" : " gosess " ,
"Options" : {
"Path" : " / " ,
"Domain" : " " ,
"MaxAge" : 28800 ,
"Secure" : false ,
"HttpOnly" : true
}
},
"Template" : {
"Root" : " base " ,
"Children" : [
" partial/menu " ,
" partial/footer "
]
},
"View" : {
"BaseURI" : " / " ,
"Extension" : " tmpl " ,
"Folder" : " template " ,
"Name" : " blank " ,
"Caching" : true
}
}Чтобы включить https, установите usehttps в True, создайте папку, называемую TLS в корне, а затем поместите файлы сертификата и ключей в эту папку.
Общественный дом:
О:
Регистрация:
Авторизоваться:
Домашний аутентификат:
Просмотреть примечания:
Добавьте примечание:
РЕДАКТИРОВАТЬ ПРИМЕЧАНИЕ:
Все отзывы приветствуются. Дайте мне знать, если у вас есть какие -либо предложения, вопросы или критика. Если что -то не идиоматическое, пожалуйста, дайте мне знать, чтобы мы могли сделать это лучше.