Docker REST API Golang - database

Hey guys i'm a new to docker, and i don't understand how to install my Golang application that have a routes, controller, and database config to Docker,after I searched on the internet, all I found was how to run 1 main.go file only, do i need to make route image, controller image, and database image to make my application run on docker?? or just make main.go image in docker to access all ?? sorry for my bad grammar.. i hope you guys understand what i'm talking about appriciate your help
Here my Main.go code
package main
import (
"dikota/config"
"dikota/models"
"dikota/routes"
"fmt"
"github.com/jinzhu/gorm"
)
var err error
func main() {
config.DB, err = gorm.Open("mysql", config.DbURL(config.BuildDBConfig()))
if err != nil {
fmt.Println("Status:", err)
}
//config.DB
defer config.DB.Close()
config.DB.AutoMigrate(&models.Konten{})
config.DB.AutoMigrate(&models.User{})
r := routes.SetupRouter()
//running
r.Run()
}
}
Here my routes code
package routes
import (
"dikota/controllers"
"time"
"github.com/gin-gonic/gin"
cors "github.com/itsjamie/gin-cors"
)
//SetupRouter Function
func SetupRouter() *gin.Engine {
router := gin.Default()
// Apply the middleware to the router (works with groups too)
router.Use(cors.Middleware(cors.Config{
Origins: "*",
Methods: "GET, PUT, POST, DELETE,OPTIONS",
RequestHeaders: "Origin, Authorization, Content-Type",
ExposedHeaders: "",
MaxAge: 50 * time.Second,
Credentials: true,
ValidateHeaders: false,
}))
// grp1 := r.Group("/user-api")
// {
// grp1.GET("user", controllers.GetUsers)
// grp1.POST("user", controllers.CreateUser)
// grp1.GET("user/:id", controllers.GetUserByID)
// grp1.PUT("user/:id", controllers.UpdateUser)
// grp1.DELETE("user/:id", controllers.DeleteUser)
// }
grp1 := router.Group("/konten-api")
{
grp1.GET("konten", controllers.GetKontens)
grp1.POST("createkonten", controllers.CreateKonten)
// grp1.GET("konten/:id", controllers.GetKontenByID)
// grp1.PUT("konten/:id", controllers.UpdateKonten)
// grp1.DELETE("konten/:id", controllers.DeleteKonten)
}
return router
}
Here my database config code
package config
import (
"fmt"
"github.com/jinzhu/gorm"
)
//DB variable
var DB *gorm.DB
//DBConfig struct
type DBConfig struct {
Host string
Port int
User string
DBName string
Password string
}
//BuildDBConfig function
func BuildDBConfig() *DBConfig {
dbConfig := DBConfig{
Host: "localhost",
Port: 3306,
User: "root",
Password: "dikota123",
DBName: "DIKOTA",
}
return &dbConfig
}
//DbURL function
func DbURL(dbConfig *DBConfig) string {
return fmt.Sprintf(
"%s:%s#tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local",
dbConfig.User,
dbConfig.Password,
dbConfig.Host,
dbConfig.Port,
dbConfig.DBName,
)
}

Related

Problem when request with axios to api go lang. Error decode NOSQL

i have this issue, when i try to post with axios in my front-ent to my back-end in go lang showed this:
timed out while checking out a connection from connection pool: context canceled; maxPoolSize: 100, connections in use by cursors: 0, connections in use by transactions: 0, connections in use by other operations: 1
I did print for see if the information was correct and is all right.
The error ocorres when Try to Decode the information of my result of MongoDB in go lang.
But this only happened when I do it with front.
If I call directly like with postman... I don't have problem.
My service that calls mongoDB.
func (p *profile)CheckInformationValid(ctx echo.Context,email string, password string, profile *models.Profile) (string, error) {
filter := map[string]interface{}{"Email": email, "PassWord": password}
result := storage.GetInstance().FindOne(ctx, "profile",filter)
fmt.Println(result)
if result == nil {
return "", errors.New("Check Information: user not find")
}
err := result.Decode(profile)
if err != nil {
fmt.Println(err)
return "",errors.New("Error Decode Profile")
}
fmt.Println(profile)
log.Infof("[CheckInformationValid] Object : %s \n", profile, "")
return profile.UserId , nil
}
the erros ocorrer in result.Decode.
my front:
export async function validLogin(email, password) {
const data = JSON.stringify({ email, password });
let headers = {
'Content-Type': 'application/json;charset=UTF-8',
};
return await axios.post('http://localhost:1323/profile/valid', data, headers)
}

trouble sending smtp email through App engine

I have created a go application that sends an email using net/smtp and PlainAuth. And everything is working fine. But when I deploy this same code on the google app engine it is not sending. If I serve using goapp serve it work locally. Below is the code:
func sendMail(body string, subject string) {
var err error
var doc bytes.Buffer
auth := smtp.PlainAuth("",
"from#gmail.com",
"********",
"smtp.gmail.com")
parameters := &SmtpTemplateData{
"from#gmail.com",
"to#gmail.com",
"Subject",
body,
}
buffer := new(bytes.Buffer)
template := template.Must(template.New("emailTemplate").Parse(emailScript()))
template.Execute(buffer, parameters)
t := template.New("emailTemplate1")
t, err = t.Parse(emailTemplate)
if err != nil {
fmt.Println("error trying to parse mail template")
}
err = t.Execute(&doc, parameters)
smtp.SendMail(
"smtp.gmail.com:587",
auth,
"from#gmail.com",
[]string{"to#gmail.com"},
doc.Bytes(),
)
}

Camel rabbitmq + convertSendAndReceive() : Could not convert incoming message with content-type [null]

I have a component that sends a message to a worker service waiting back the result.
#Autowired
private RabbitTemplate rabbit;
[...]
Object response = rabbit.convertSendAndReceive("testQ", ...);
The worker service is implemented with Apache Camel rabbitmq route:
from("rabbitmq://localhost/myExchange?declare=false&routingKey=testQ&queue=testQ")
.routeId("myCamelRoute")
.process(myProcessor)
.to("log:myLog");
myProcessor handles the message and logs out the Camel Message headers:
__TypeId__=...
breadcrumbId=...
rabbitmq.CONTENT_ENCODING=UTF-8
rabbitmq.CONTENT_TYPE=application/json
rabbitmq.CORRELATIONID=7e390b6b-d30f-4f26-ba44-33fb887db0e8
rabbitmq.DELIVERY_TAG=4
rabbitmq.EXCHANGE_NAME=
rabbitmq.PRIORITY=0
rabbitmq.REPLY_TO=amq.rabbitmq.reply-to.g2dkABNyYWJiaXRAOWU5ZjkxNDI4ZWRiAAAJgwAAADUC.5+kPXXxaXhoYo7A4T0HSZQ==
rabbitmq.ROUTING_KEY=testQ
The message header apparently contains rabbitmq.CONTENT_TYPE=application/json on the worker side but this info seems to get "lost" when the response message goes back:
o.s.a.s.c.Jackson2JsonMessageConverter : Could not convert
incoming message with content-type [null]
Any idea what is wrong here?
I've seen the same error using the RabbitMQ Management console when using a Headers field.
Passing "content_type":"application/json" as a message Property worked fine.
EDIT: Actually, it seems that chrome autocomplete is not working properly. I manually typed the property and worked fine too
I faced the same issue. It seems to be a problem between RabbitMQ Management console and the Spring consumer.
Based on this, I override the fromMessage method from Jackson2JsonMessageConverter, and forced the contentType to be application/json, and worked fine
My stack was:
org.springframework: 4.3.6.RELEASE
org.springframework.amqp : 1.7.14.RELEASE
com.fasterxml.jackson.core: 2.11.2
import org.springframework.amqp.core.Message;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
public class JacksonMessageConverter extends Jackson2JsonMessageConverter {
public JacksonMessageConverter() {
super();
}
#Override
public Object fromMessage(Message message) {
message.getMessageProperties().setContentType("application/json");
return super.fromMessage(message);
}
}
and then I used in my rabbit configuration
#Bean
public MessageConverter messageConverter() {
JacksonMessageConverter jsonMessageConverter = new JacksonMessageConverter();
jsonMessageConverter.setClassMapper(classMapper());
return jsonMessageConverter;
}
Other solution was to create a basic application in GO to publish the message, add the content-type and it worked fine, since the problems appears to be in RabbitMQ Management console.
My script in go:
// MqFactory - Creates a connection with mq
func MqFactory() *amqp.Connection {
mqURI, err := amqp.ParseURI(createAmqpURI())
if err != nil {
fmt.Printf("Failed on parse mq uri: %s", err)
}
conn, err := amqp.Dial(mqURI.String())
if err != nil {
failOnError(err, "Failed to connect to MQ")
} else {
fmt.Println("Connection established with MQ")
}
sendMessage(conn)
return conn
}
func sendMessage(conn *amqp.Connection) {
channel, err := conn.Channel()
if err != nil {
failOnError(err, "Failed 1")
}
err2 := channel.Publish(
"<exchange>",
"<routin_key>",
false,
false,
amqp.Publishing{
Headers: amqp.Table{
"__TypeId__": "<type_id>", // If needed
},
ContentType: "application/json",
Body: []byte("<body>"),
},
)
if err2 != nil {
failOnError(err2, "Failed 2")
}
}
func createAmqpURI() string {
host := os.Getenv("MQ_HOST")
port := os.Getenv("MQ_PORT")
usr := os.Getenv("MQ_USR")
pwd := os.Getenv("MQ_PWD")
return "amqp://" + usr + ":" + pwd + "#" + host + ":" + port
}
func failOnError(err error, msg string) {
println(msg)
if err != nil {
fmt.Printf("%s: %s", msg, err)
}
}
if spring-amqp:
#Bean
public CachingConnectionFactory cachingConnectionFactory() {
final CachingConnectionFactory factory = new CachingConnectionFactory();
factory.setUsername(username);
factory.setPassword(password);
factory.setHost(host);
factory.setPort(port);
return factory;
}
#Bean
#DependsOn("cachingConnectionFactory")
public RabbitTemplate rabbitTemplate(CachingConnectionFactory cachingConnectionFactory) {
RabbitTemplate rabbitTemplate = new RabbitTemplate(cachingConnectionFactory);
rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
return rabbitTemplate;
}

Is it possible to use sessionauth of martini with Datastore on google app engine?

I tried to use the example of sessionauth of martini on google app engine and want to save login list in Datastore, but did not know how to deal with appengine.Context. Does anyone has the experience?
Thank you.
Update:
// Auth example is an example application which requires a login
// to view a private link. The username is "testuser" and the password
// is "password". This will require GORP and an SQLite3 database.
package ahl
import (
//"fmt"
"github.com/go-martini/martini"
"github.com/hnakamur/gaesessions"
"github.com/martini-contrib/binding"
"github.com/martini-contrib/render"
"github.com/martini-contrib/sessionauth"
"github.com/martini-contrib/sessions"
"net/http"
)
//var namespace string = "ahl"
func init() {
//store := sessions.NewCookieStore([]byte("secret123"))
store := gaesessions.NewDatastoreStore("", gaesessions.DefaultNonPersistentSessionDuration)
m := martini.Classic()
m.Use(render.Renderer())
// Default our store to use Session cookies, so we don't leave logged in
// users roaming around
//store.Options(sessions.Options{
// MaxAge: 0,
//})
m.Use(sessions.Sessions("my_session", store))
m.Use(sessionauth.SessionUser(GenerateAnonymousUser))
sessionauth.RedirectUrl = "/new-login"
sessionauth.RedirectParam = "new-next"
m.Get("/", func(r render.Render) {
r.HTML(200, "index", nil)
})
m.Get("/new-login", func(r render.Render) {
r.HTML(200, "login", nil)
})
m.Post("/new-login", binding.Bind(MyUserModel{}), func(session sessions.Session, postedUser MyUserModel, r render.Render, req *http.Request) {
// You should verify credentials against a database or some other mechanism at this point.
// Then you can authenticate this session.
//user := MyUserModel{}
user := MyUserModel{1, "testuser", "password", false}
//err := dbmap.SelectOne(&user, "SELECT * FROM users WHERE username = $1 and password = $2", postedUser.Username, postedUser.Password)
//if err != nil {
// r.Redirect(sessionauth.RedirectUrl)
// return
//} else {
err := sessionauth.AuthenticateSession(session, &user)
if err != nil {
r.JSON(500, err)
}
params := req.URL.Query()
redirect := params.Get(sessionauth.RedirectParam)
r.Redirect(redirect)
return
//}
})
m.Get("/private", sessionauth.LoginRequired, func(r render.Render, user sessionauth.User) {
r.HTML(200, "private", user.(*MyUserModel))
})
m.Get("/logout", sessionauth.LoginRequired, func(session sessions.Session, user sessionauth.User, r render.Render) {
sessionauth.Logout(session, user)
r.Redirect("/")
})
http.Handle("/", m)
}
Yes, it should be possible. The sessionauth package requires you to pass it a *sessions.Store, and there is a gaesessions package that can replace the default cookie/file stores: https://github.com/hnakamur/gaesessions
The sessionauth package has a full example (https://github.com/martini-contrib/sessionauth/blob/master/example/auth_example.go) - just replace sessions.NewCookieStore with gaesessions.NewDatastoreStore.

go gorilla/sessions angularjs and path, session values not saved (find the bug/place the blame)

Ok where to start...
The problem is when I set the session's Path to "/" the session doesn't get saved.
And I set Path because when posting to a path that is not the path where the session gets saved, aka session.Save() is called the session value "user" is empty|nil|not set.
So I set Path: "/", but the session isn't saved. When checking Chromium I see that the cookie is set. I don't know where the problem is. Is it in gorilla/sessions? Is it in AngularJS? HTML5 mode is off in angular.
So to rephrase, this happens because /api/1.0/community is a different path than /api/1.0/user where the sessions.Save(r,w) function is called and that's why I set Path: "/", . But when Path is "/" the session value "user" isn't saved.
main.go
var (
sessionStore *sessions.CookieStore
sessionAuthKey []byte = make([]byte, 64)
sessionCryptKey []byte = make([]byte, 32)
router *mux.Router = mux.NewRouter()
)
func init() {
// Generate Session Secret
sessionAuthKey = securecookie.GenerateRandomKey(64)
sessionCryptKey = securecookie.GenerateRandomKey(32)
// Create Session
sessionStore = sessions.NewCookieStore(sessionAuthKey, sessionCryptKey)
sessionStore.Options = &sessions.Options{
Domain: ".mango.dev",
Path: "/",
MaxAge: 0,
}
}
func main() {
api := router.PathPrefix("/api/1.0").Subrouter()
api.HandleFunc("/user/register", UserRegisterHandler).Methods("POST")
api.HandleFunc("/user/authenticate", UserAuthenticateHandler).Methods("POST")
api.HandleFunc("/user/endsession", UserLogoutHandler).Methods("POST")
api.HandleFunc("/user/profile", UserProfileHandler).Methods("GET")
api.HandleFunc("/user/profile", UserUpdateProfileHandler).Methods("POST")
api.HandleFunc("/user/reset_request", UserResetRequestHandler).Methods("POST")
api.HandleFunc("/user/reset_password", UserResetPasswordHandler).Methods("POST")
api.HandleFunc("/user/loginstatus", UserLoginStatusHandler).Methods("GET")
api.HandleFunc("/forums/directory", ForumsDirectoryHandler).Methods("GET")
api.HandleFunc("/community/list", CommunityListHandler).Methods("GET")
api.HandleFunc("/community/show", CommunityShowHandler).Methods("GET")
api.HandleFunc("/community/create", CommunityCreateHandler).Methods("POST")
api.HandleFunc("/community/edit", CommunityEditHandler).Methods("GET")
static := router.PathPrefix("/").Subrouter()
static.Methods("GET").Handler(http.FileServer(http.Dir("webapp/public")))
go func() {
if err := http.ListenAndServe(":8080", Log(router)); err != nil {
log.Fatal(err)
}
}()
if err := http.ListenAndServeTLS(":8443", "ssl/mango.dev.crt", "ssl/mango.dev.pem", Log(router)); err != nil {
log.Fatal(err)
}
}
handlers.go
func UserAuthenticateHandler(w http.ResponseWriter, r *http.Request) {
// ...
if valid {
tu.Name = user.UserProfile.Name
data["user"] = tu
data["redirect"] = "/user/profile"
user.Login(r.UserAgent(), r.RemoteAddr)
session, _ := sessionStore.Get(r, "p")
session.Values["user"] = user.Id.Hex()
if tc.Rememberme {
session.Options = &sessions.Options{
Domain: ".mango.dev",
Path: "/",
MaxAge: 86400 * 30 * 12,
}
}
session.Save(r, w)
}
The problem was dundundun I had old cookies stored from before the change that had the Path "/api/1.0/user" and apparently this caused a problem since, I imagine, the longer or deeper path has priority over the shorter, root path, which makes perfect sense in retrospect.

Resources