[go-nuts] Multipar/related Request in golang

2024-06-17 Thread Afriyie Abraham Kwabena
Hi,

AM trying to prepare a multipart/related message which involve JSON data 
n1n2Request.JsonData and a binary data binaryData to be sent in HTTP 
request, however, am having issue abou how to set the boundries in the 
function below. The server is logging "Failed to parse boundary. 
missing/invalide boundary". I need help to set the boundaries correctly in 
the function below. Thanks in advance.



func CreateMultipartRelatedN1N2MessageTransferRequest(inputData 
models.InputData) (*models.N1N2MessageTransferRequest, string, error) {
// Create a buffer to hold the multipart data
var buf bytes.Buffer

// Create a multipart writer with "multipart/related" type
writer := multipart.NewWriter(&buf)

// Define the boundary for the multipart/related content
boundary := writer.Boundary()

// Create the N1N2MessageTransferRequest object
n1n2Request := models.N1N2MessageTransferRequest{}

// Get LMF instanceID (example placeholder, replace with actual logic)
_, _, nfId, _, _ := config.Cfg.GetServerInfo()

// Populate the N1N2MessageTransferReqData
n1n2Request.JsonData = &models.N1N2MessageTransferReqData{
N1MessageContainer: &models.N1MessageContainer{
N1MessageClass: models.N1MessageClass_LPP,
N1MessageContent: &models.RefToBinaryData{
ContentId: "N1LoInformation",
},
NfId: nfId,
},
LcsCorrelationId:   inputData.CorrelationID,
N1n2FailureTxfNotifURI: "",
}

// Add the JSON part as the root body part
jsonPartHeader := textproto.MIMEHeader{}
jsonPartHeader.Set("Content-Type", "application/json; charset=UTF-8")
jsonPartHeader.Set("Content-ID", "jsondata")
jsonPart, err := writer.CreatePart(jsonPartHeader)
if err != nil {
return nil, "", fmt.Errorf("error creating JSON part: %v", err)
}

jsonBytes, err := json.Marshal(n1n2Request.JsonData)
if err != nil {
return nil, "", fmt.Errorf("error marshaling JSON data: %v", err)
}
_, err = jsonPart.Write(jsonBytes)
if err != nil {
return nil, "", fmt.Errorf("error writing JSON data: %v", err)
}

// Create the LPP message
lppMessage := models.LPPMessage{
TransactionID: &models.LPPTransactionID{
TransactionNumber: common.GenerateNumber(),
Initiator: int(models.LocationServer),
},
SequenceNumber: common.GenerateNumber(),
LPPMessageBody: &models.LPPMessageBody{
C1: &models.C1{
RequestLocationInformation: 
&models.RequestLocationInformation{
CriticalExtensions: &models.CriticalExtensions{
C1: &models.CriticalExtensionsC1{
RequestLocationInformationR9: 
&models.RequestLocationInformationR9IEs{
CommonIEsRequestLocationInformation: 
&models.CommonIEsRequestLocationInformation{
LocationInformationType: 
int(models.LocationEstimateRequired),
PeriodicalReporting: 
&models.PeriodicalReportingCriteria{
ReportingAmount:   int(models.RA1),
ReportingInterval: int(models.RI32),
},
LocationCoordinateTypes: 
&models.LocationCoordinateTypes{
EllipsoidPoint: true,
},
VelocityTypes: &models.VelocityTypes{
HorizontalVelocity: true,
},
},
},
},
},
},
},
},
EndTransaction: true,
}

// Encode the LPP message using ASN.1 PER encoding
binaryData, err := aper.Marshal(lppMessage)
if err != nil {
logger.Log.Error().Msgf("Error encoding, aper.Marshal error: %v", 
err)
return nil, "", err
}

// Add the binary part with a Content-ID header
binaryPartHeader := textproto.MIMEHeader{}
binaryPartHeader.Set("Content-ID", "n1message")
binaryPartHeader.Set("Content-Type", "application/vnd.3gpp.5gnas")
binaryPart, err := writer.CreatePart(binaryPartHeader)
if err != nil {
return nil, "", fmt.Errorf("error creating binary part: %v", err)
}

// Write the encoded binary data to the binary part
_, err = binaryPart.Write(binaryData)
if err != nil {
return nil, "", fmt.Errorf("error writing binary data: %v", err)
}

// Close the multipart writer to finalize the form data
err = writer.Close()
if err != nil {
return nil, "", fmt.Errorf("error closing multipart writer: %v", 
err)
}

// Attach the buffer's content as the binary data

[go-nuts] How to detect HTTP client stop polling at the server side

2020-11-14 Thread Afriyie Abraham Kwabena
Hi,

My  question is  about multiple HTTP client polling an HTTP server randomly 
with a PATCH request to update a resource at the server running in front of 
MongoDB. The clients poll with their different ids and a valid time in 
their request. At the server, I can keep their ids and their different 
times. 
How can detect at the server if a specific client stop polling. I would 
like to write a function that detect at the HTTP server if a specific 
client stop polling and then remove its resources after some time from a 
database.  Am using gorilla/mux package for the server. Any  help, am new 
to Golang programming. 

Thanks in advance

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/8658410c-5cac-4dff-80e3-ebb1b8bbb5een%40googlegroups.com.


Re: [go-nuts] How to detect HTTP client stop polling at the server side

2020-11-16 Thread Afriyie Abraham Kwabena
Hi ,

You are right but am new to programming and currently this what i have done.
I have an http server handler that receives the PATCH request and stores 
the id and the current time stamp of the request.
But my problem is how to write the worker function to do the clean up every 
X seconds.

Code:
func UpdateData(response http.ResponseWriter, request *http.Request) {

var (
localVarHTTPMethod = http.MethodPatch
patchItems model.PatchItem
)

id := config.GetIdFromRequest(request)

if request.Method == localVarHTTPMethod {

err := json.NewDecoder(request.Body).Decode(&patchItems)
if err != nil {
common.WriteError(response, common.ErrBadRequest)
return
}

defer request.Body.Close()

var idtime = make(map[string]string)

delete(idtime, id) // delete if already exist 
idtime[id] = time.Now() // store id and time stamp in map 

// how do i write a worker to the clean up after every X seconds? 

} else {
common.WriteError(response, common.ErrMethodNotAllowed)
return
}
}

BR
Abraham



On Sunday, November 15, 2020 at 9:01:27 AM UTC+2 Shulhan wrote:

>
> > On 14 Nov 2020, at 20.06, Afriyie Abraham Kwabena  
> wrote:
> > 
> > Hi,
> > 
> > My question is about multiple HTTP client polling an HTTP server 
> randomly with a PATCH request to update a resource at the server running in 
> front of MongoDB. The clients poll with their different ids and a valid 
> time in their request. At the server, I can keep their ids and their 
> different times. 
> > How can detect at the server if a specific client stop polling. I would 
> like to write a function that detect at the HTTP server if a specific 
> client stop polling and then remove its resources after some time from a 
> database. Am using gorilla/mux package for the server. Any help, am new to 
> Golang programming. 
> > 
>
> I think this is not Go specific, but more like engineering in general.
>
> My suggestion is you can store the last time when user request to PATCH 
> endpoint in some storage or internal memory (like map[userID]timestamp) and 
> then have some worker that check the timestamp to clean it up every X 
> seconds or minutes.

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/7798fe2c-d176-4514-8fe0-04b6e19f4399n%40googlegroups.com.


Re: [go-nuts] How to detect HTTP client stop polling at the server side

2020-11-17 Thread Afriyie Abraham Kwabena
HI,

This is what I have tried so far but am not able to get the time difference 
in seconds. I mean the time differences between the time stored in the 
map[string]time.Time and
the current time in seconds.

code:

type Server struct {
idtime map[string]time.Time
}

var my = Server{}

func main() {
r := mux.NewRouter()
usersData := r.PathPrefix("/users").Subrouter()
   
 usersData.Path("/{id}").Methods(http.MethodPatch).HandlerFunc(UpdateData)

fmt.Println("Start listening")
fmt.Println(http.ListenAndServe(":8080", r))
}

func UpdateData(response http.ResponseWriter, request *http.Request) {

var (
localVarHTTPMethod = http.MethodPatch
patchItems model.PatchItem
)

id := config.GetIdFromRequest(request)

if request.Method == localVarHTTPMethod {

err := json.NewDecoder(request.Body).Decode(&patchItems)
if err != nil {
common.WriteError(response, common.ErrBadRequest)
return
}

defer request.Body.Close()

my.idtime = make(map[string]time.Time)
my.idtime[id] = time.Now()

go func() {
for keyid, t := range my.idtime {

ts := t.Format(time.RFC3339)

v, err := time.Parse(time.RFC3339, ts)
if err != nil {
fmt.Println(err)
os.Exit(1)
}

timeRemaining := getTimeRemaining(v)

if timeRemaining.S >= 60 {
// delete resouce in database after 60 seconds
deleteResourceUsingIdkey(keyid)
}
}
}()

common.RespondWith3gppJsonPatchJson(response, http.StatusNoContent, 
nil)
} else {

common.WriteError(response, common.ErrMethodNotAllowed)
return
}
}

type count struct {
S int
}

func getTimeRemaining(t time.Time) count {
currentTime := time.Now()
difference := t.Sub(currentTime)

seconds := int(difference.Seconds())

return count{
S: seconds,
}
}

func deleteResourceUsingIdkey(idkey string) {
// do delete here
}

Any help.


On Tuesday, November 17, 2020 at 10:34:39 AM UTC+2 Anderson Queiroz wrote:

> Just one thing to keep in mind. Likely you have more than one serve 
> instance running to process the requests. Thus it might happen the client 
> will poll a different server on every request. Just imagine you have 
> servers A, B, C behind a load balance and the domain example.com. As the 
> client is pooling example.com, the first request might reach A, the 
> second B and the third C. Now you have the 3 servers tracking the same 
> client. It might happen server A doesn't receive any request from the 
> client for a while, but not because the client isn't pooling any more, but 
> because all requests are being directed to either B or C.
>
> On Tuesday, 17 November 2020 at 07:12:18 UTC+1 Shulhan wrote:
>
>>
>>
>> > On 16 Nov 2020, at 16.24, Afriyie Abraham Kwabena  
>> wrote: 
>> > 
>> > Hi , 
>> > 
>> > You are right but am new to programming and currently this what i have 
>> done. 
>> > I have an http server handler that receives the PATCH request and 
>> stores the id and the current time stamp of the request. 
>> > But my problem is how to write the worker function to do the clean up 
>> every X seconds. 
>> > 
>> > Code: 
>> > func UpdateData(response http.ResponseWriter, request *http.Request) { 
>> > 
>> > var ( 
>> > localVarHTTPMethod = http.MethodPatch 
>> > patchItems model.PatchItem 
>> > ) 
>> > 
>> > id := config.GetIdFromRequest(request) 
>> > 
>> > if request.Method == localVarHTTPMethod { 
>> > 
>> > err := json.NewDecoder(request.Body).Decode(&patchItems) 
>> > if err != nil { 
>> > common.WriteError(response, common.ErrBadRequest) 
>> > return 
>> > } 
>> > 
>> > defer request.Body.Close() 
>> > 
>> > var idtime = make(map[string]string) 
>> > 
>> > delete(idtime, id) // delete if already exist 
>> > idtime[id] = time.Now() // store id and time stamp in map 
>>
>> You should store idtime inside the server/service type (the one that have 
>> HTTP handlers). For example, 
>>
>>  
>> type Server struct { 
>> idtime map[string]string 
>> } 
>>
>> func (my *Server) UpdateData(...) { 
>> ... 
>> my.idtime[id] = time.Now() 
>> ... 
>> } 
>>  
>>
>> > 
>> > // how do i write a worker to the clean up after every X seconds? 
>> > 
>>
>

Re: [go-nuts] How to detect HTTP client stop polling at the server side

2020-11-17 Thread Afriyie Abraham Kwabena
Hi,

I have made changes according to the comments and also simply the main 
function but am not sure if the worker go routine works. 
This what i did:

type Route struct {
Namestring
Method  string
Pattern string
HandlerFunc http.HandlerFunc
}

var idtime = make(map[string]int64)

func UpdateData(response http.ResponseWriter, request *http.Request) {

var (
localVarHTTPMethod = http.MethodPatch
patchItems model.PatchItem
)

id := config.GetIdFromRequest(request)

if request.Method == localVarHTTPMethod {

err := json.NewDecoder(request.Body).Decode(&patchItems)
if err != nil {
common.WriteError(response, common.ErrBadRequest)
return
}

defer request.Body.Close()

idtime[id] = time.Now().Unix()

common.RespondWith3gppJsonPatchJson(response, http.StatusNoContent, 
nil)
} else {
common.WriteError(response, common.ErrMethodNotAllowed)
return
}
}

var (
mu  sync.Mutex
ctx = context.Background()
)

func worker() {
mu.Lock()
for keyid := range idtime {

d := time.Now().Unix() - idtime[keyid]
if d >= 60 {
// delete resouce in database after 60 seconds
_ = DeleteNFInstance(ctx, keyid)
}
}
mu.Unlock()
}

// Delete info
func DeleteNFInstance(ctx context.Context, nfinstanceId string) bool {
filter := bson.M{"_id": nfinstanceId}
_, err := db.Collection(COLLECTION).DeleteOne(ctx, filter)
if err != nil {
return false
}
return true
}

type Routes []Route

func NewRouter() *mux.Router {
router := mux.NewRouter().StrictSlash(true)
for _, route := range routes {
var handler http.Handler
handler = route.HandlerFunc

router.
Methods(route.Method).
Path(route.Pattern).
Name(route.Name).
Handler(handler)
}

return router
}

var routes = Routes{

Route{
"UpdateData",
strings.ToUpper("Patch"),
"/users/{id}",
UpdateData,
},
}

// main function
func main() {
r := NewRouter()

go worker()

fmt.Println("Start listening")
fmt.Println(http.ListenAndServe(":8080", r))
}

I appreciate your help but am still not able to it work.


On Tuesday, November 17, 2020 at 3:48:44 PM UTC+2 Shulhan wrote:

> Hi Afriyie,
>
> Looks like you almost there ;)
>
> > On 17 Nov 2020, at 20.11, Afriyie Abraham Kwabena  
> wrote:
> > 
> > HI,
> > 
> > This is what I have tried so far but am not able to get the time 
> difference in seconds. I mean the time differences between the time stored 
> in the map[string]time.Time and
> > the current time in seconds.
> > 
> > code:
> > 
> > type Server struct {
> > idtime map[string]time.Time
> > }
> > 
> > var my = Server{}
> > 
> > func main() {
> > r := mux.NewRouter()
> > usersData := r.PathPrefix("/users").Subrouter()
> > usersData.Path("/{id}").Methods(http.MethodPatch).HandlerFunc(UpdateData)
> > 
>
> Based on my understanding (I have never use mux before), the UpdateDate 
> function will be running concurrently as goroutine. Lets say that we have 
> three PATCH requests at the same time, there will be three UpdateData 
> running concurrently or in parallel.
>
> > fmt.Println("Start listening")
> > fmt.Println(http.ListenAndServe(":8080", r))
> > }
> > 
> > func UpdateData(response http.ResponseWriter, request *http.Request) {
> > 
> > var (
> > localVarHTTPMethod = http.MethodPatch
> > patchItems model.PatchItem
> > )
> > 
> > id := config.GetIdFromRequest(request)
> > 
> > if request.Method == localVarHTTPMethod {
> > 
> > err := json.NewDecoder(request.Body).Decode(&patchItems)
> > if err != nil {
> > common.WriteError(response, common.ErrBadRequest)
> > return
> > }
> > 
> > defer request.Body.Close()
> > 
> > my.idtime = make(map[string]time.Time)
>
> Since the UpdateData is running independently for each request, you should 
> initialize this once, in the main, otherwise each UpdateData routine will 
> reset the idtime variable.
>
> > my.idtime[id] = time.Now()
> > 
> > go func() {
> > for keyid, t := range my.idtime {
> > 
> > ts := t.Format(time.RFC3339)
> > 
> > v, err := time.Parse(time.RFC3339, ts)
> > if err != nil {
> > fmt.Println(err)
> > os.Exit(1)
> > }
> > 
> > timeRemaining := getTimeRemaining(v)
> > 
> > if timeRemaining.S >= 60 {
> > // delete resouce in databa

Re: [go-nuts] How to detect HTTP client stop polling at the server side

2020-11-17 Thread Afriyie Abraham Kwabena
Hi,

The UpdateData function is the HTTP handler for the route which matches the 
URL and  is called after the mux.Router after receiving an incoming request 
matches the incoming request
 against the registered route. 

BR
Afriyie


On Tuesday, November 17, 2020 at 7:33:50 PM UTC+2 Afriyie Abraham Kwabena 
wrote:

> Hi,
>
> I have made changes according to the comments and also simply the main 
> function but am not sure if the worker go routine works. 
> This what i did:
>
> type Route struct {
> Namestring
> Method  string
> Pattern string
> HandlerFunc http.HandlerFunc
> }
>
> var idtime = make(map[string]int64)
>
>
> func UpdateData(response http.ResponseWriter, request *http.Request) {
>
> var (
> localVarHTTPMethod = http.MethodPatch
> patchItems model.PatchItem
> )
>
> id := config.GetIdFromRequest(request)
>
> if request.Method == localVarHTTPMethod {
>
> err := json.NewDecoder(request.Body).Decode(&patchItems)
> if err != nil {
> common.WriteError(response, common.ErrBadRequest)
> return
> }
>
> defer request.Body.Close()
>
> idtime[id] = time.Now().Unix()
>
>
> common.RespondWith3gppJsonPatchJson(response, 
> http.StatusNoContent, nil)
> } else {
> common.WriteError(response, common.ErrMethodNotAllowed)
> return
> }
> }
>
> var (
> mu  sync.Mutex
> ctx = context.Background()
> )
>
> func worker() {
> mu.Lock()
> for keyid := range idtime {
>
> d := time.Now().Unix() - idtime[keyid]
> if d >= 60 {
>
> // delete resouce in database after 60 seconds
> _ = DeleteNFInstance(ctx, keyid)
> }
> }
> mu.Unlock()
> }
>
> // Delete info
> func DeleteNFInstance(ctx context.Context, nfinstanceId string) bool {
> filter := bson.M{"_id": nfinstanceId}
> _, err := db.Collection(COLLECTION).DeleteOne(ctx, filter)
> if err != nil {
> return false
> }
> return true
> }
>
> type Routes []Route
>
> func NewRouter() *mux.Router {
> router := mux.NewRouter().StrictSlash(true)
> for _, route := range routes {
> var handler http.Handler
> handler = route.HandlerFunc
>
> router.
> Methods(route.Method).
> Path(route.Pattern).
> Name(route.Name).
> Handler(handler)
> }
>
> return router
> }
>
> var routes = Routes{
>
> Route{
> "UpdateData",
> strings.ToUpper("Patch"),
> "/users/{id}",
> UpdateData,
> },
> }
>
> // main function
> func main() {
>     r := NewRouter()
>
> go worker()
>
>
> fmt.Println("Start listening")
> fmt.Println(http.ListenAndServe(":8080", r))
> }
>
> I appreciate your help but am still not able to it work.
>
>
> On Tuesday, November 17, 2020 at 3:48:44 PM UTC+2 Shulhan wrote:
>
>> Hi Afriyie, 
>>
>> Looks like you almost there ;) 
>>
>> > On 17 Nov 2020, at 20.11, Afriyie Abraham Kwabena  
>> wrote: 
>> > 
>> > HI, 
>> > 
>> > This is what I have tried so far but am not able to get the time 
>> difference in seconds. I mean the time differences between the time stored 
>> in the map[string]time.Time and 
>> > the current time in seconds. 
>> > 
>> > code: 
>> > 
>> > type Server struct { 
>> > idtime map[string]time.Time 
>> > } 
>> > 
>> > var my = Server{} 
>> > 
>> > func main() { 
>> > r := mux.NewRouter() 
>> > usersData := r.PathPrefix("/users").Subrouter() 
>> > 
>> usersData.Path("/{id}").Methods(http.MethodPatch).HandlerFunc(UpdateData) 
>> > 
>>
>> Based on my understanding (I have never use mux before), the UpdateDate 
>> function will be running concurrently as goroutine. Lets say that we have 
>> three PATCH requests at the same time, there will be three UpdateData 
>> running concurrently or in parallel. 
>>
>> > fmt.Println("Start listening") 
>> > fmt.Println(http.ListenAndServe(":8080", r)) 
>> > } 
>> > 
>> > func UpdateData(response http.ResponseWriter, request *http.Request) { 
>> > 
>> > var ( 
>> > localVarHTTPMethod = http.MethodPatch 
>> > patchItems model.PatchItem 
>

Re: [go-nuts] How to detect HTTP client stop polling at the server side

2020-11-18 Thread Afriyie Abraham Kwabena
Hi Sulhan,  Anderson,

Thanks for your guidance. It works now using time.Ticker

func worker() {
tiker := time.NewTicker(30 * time.Second)
for _ = range tiker.C {
mu.Lock()
for keyid := range idtime {

d := time.Now().Unix() - idtime[keyid]
if d >= 60 {
// delete resouce in database after 60 seconds
_ = DeleteNFInstance(ctx, keyid)
}
}
mu.Unlock()
}
}

BR
Abraham



On Tuesday, November 17, 2020 at 9:41:01 PM UTC+2 Shulhan wrote:

>
>
> > On 18 Nov 2020, at 01.06, Afriyie Abraham Kwabena  
> wrote:
> > 
> > Hi,
> > 
> > The UpdateData function is the HTTP handler for the route which matches 
> the URL and is called after the mux.Router after receiving an incoming 
> request matches the incoming request
> > against the registered route. 
>
> ...
>
> > var idtime = make(map[string]int64)
> > 
> > 
> > func UpdateData(response http.ResponseWriter, request *http.Request) {
> > 
> > var (
> > localVarHTTPMethod = http.MethodPatch
> > patchItems model.PatchItem
> > )
> > 
> > id := config.GetIdFromRequest(request)
> > 
> > if request.Method == localVarHTTPMethod {
> > 
> > err := json.NewDecoder(request.Body).Decode(&patchItems)
> > if err != nil {
> > common.WriteError(response, common.ErrBadRequest)
> > return
> > }
> > 
> > defer request.Body.Close()
> > 
> > idtime[id] = time.Now().Unix()
> > 
>
> We still may have data race here.
>
> > 
> > func worker() {
> > mu.Lock()
> > for keyid := range idtime {
> > 
> > d := time.Now().Unix() - idtime[keyid]
> > if d >= 60 {
> > 
> > // delete resouce in database after 60 seconds
> > _ = DeleteNFInstance(ctx, keyid)
> > }
> > }
> > mu.Unlock()
> > }
> > 
>
> ...
>
> > // main function
> > func main() {
> > r := NewRouter()
> > 
> > go worker()
> > 
> > 
> > fmt.Println("Start listening")
> > fmt.Println(http.ListenAndServe(":8080", r))
> > }
> > 
> > I appreciate your help but am still not able to it work.
> > 
>
> Looks like your worker only loop once and then it finished. Either you use 
> time.Sleep() to repeat the loop inside loop or use time.Ticker [1].
>
> [1] https://pkg.go.dev/time#Ticker
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/cc7b885f-074a-4b23-9f4c-08d4a3a7ac62n%40googlegroups.com.


[go-nuts] How to detect if transport connection break

2020-11-20 Thread Afriyie Abraham Kwabena

Hi,

My basic understanding of HTTP protocol is that an HTTP client sent 
request, get response from the HTTP server and then the connection is 
closed.

My question is how can an HTTP client detect if the underling transport 
connection break. For example if the HTTP server shutdown, is there a way 
to detect that at the client so that the client can start a persistent 
request. 

If possible, how can I do that in golang HTTP client? 

BR
Abraham


-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/4937b529-c1aa-4425-8b81-01214c1fc1f7n%40googlegroups.com.


Re: [go-nuts] How to detect if transport connection break

2020-11-20 Thread Afriyie Abraham Kwabena
Hi,

Am new to programming and if you could explain further what you mean by 
long lived process.
 

On Friday, November 20, 2020 at 11:41:42 AM UTC+2 amits...@gmail.com wrote:

>
>
> On Fri, 20 Nov 2020, 7:51 pm Afriyie Abraham Kwabena, <
> afriyie...@gmail.com> wrote:
>
>>
>> Hi,
>>
>> My basic understanding of HTTP protocol is that an HTTP client sent 
>> request, get response from the HTTP server and then the connection is 
>> closed.
>>
>> My question is how can an HTTP client detect if the underling transport 
>> connection break. For example if the HTTP server shutdown, is there a way 
>> to detect that at the client so that the client can start a persistent 
>> request. 
>>
>> If possible, how can I do that in golang HTTP client? 
>>
>
> Are you thinking about implementing a connection pool for your long lived 
> process?
>
>
>
>> BR
>> Abraham
>>
>>
>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "golang-nuts" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to golang-nuts...@googlegroups.com.
>> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/golang-nuts/4937b529-c1aa-4425-8b81-01214c1fc1f7n%40googlegroups.com
>>  
>> <https://groups.google.com/d/msgid/golang-nuts/4937b529-c1aa-4425-8b81-01214c1fc1f7n%40googlegroups.com?utm_medium=email&utm_source=footer>
>> .
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/ce2735a8-68e7-47e1-9eb4-59a825b1eb94n%40googlegroups.com.


Re: [go-nuts] How to detect if transport connection break

2020-11-20 Thread Afriyie Abraham Kwabena
Hi,

Yes, that is what intend to implement. Can you help with some information 
about how
I could implement it. 
If possible some libraries or example code.

Abraham

On Friday, November 20, 2020 at 1:07:12 PM UTC+2 Afriyie Abraham Kwabena 
wrote:

> Hi,
>
> Am new to programming and if you could explain further what you mean by 
> long lived process.
>  
>
> On Friday, November 20, 2020 at 11:41:42 AM UTC+2 amits...@gmail.com 
> wrote:
>
>>
>>
>> On Fri, 20 Nov 2020, 7:51 pm Afriyie Abraham Kwabena, <
>> afriyie...@gmail.com> wrote:
>>
>>>
>>> Hi,
>>>
>>> My basic understanding of HTTP protocol is that an HTTP client sent 
>>> request, get response from the HTTP server and then the connection is 
>>> closed.
>>>
>>> My question is how can an HTTP client detect if the underling transport 
>>> connection break. For example if the HTTP server shutdown, is there a way 
>>> to detect that at the client so that the client can start a persistent 
>>> request. 
>>>
>>> If possible, how can I do that in golang HTTP client? 
>>>
>>
>> Are you thinking about implementing a connection pool for your long lived 
>> process?
>>
>>
>>
>>> BR
>>> Abraham
>>>
>>>
>>> -- 
>>> You received this message because you are subscribed to the Google 
>>> Groups "golang-nuts" group.
>>> To unsubscribe from this group and stop receiving emails from it, send 
>>> an email to golang-nuts...@googlegroups.com.
>>> To view this discussion on the web visit 
>>> https://groups.google.com/d/msgid/golang-nuts/4937b529-c1aa-4425-8b81-01214c1fc1f7n%40googlegroups.com
>>>  
>>> <https://groups.google.com/d/msgid/golang-nuts/4937b529-c1aa-4425-8b81-01214c1fc1f7n%40googlegroups.com?utm_medium=email&utm_source=footer>
>>> .
>>>
>>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/d2125284-5529-4c95-82c7-3a8dac7fde78n%40googlegroups.com.


Re: [go-nuts] How to detect HTTP client stop polling at the server side

2020-11-26 Thread Afriyie Abraham Kwabena
Hi,

Am experiancing data race warning with my pollingworker function below even 
though when i build with the  -race flag i do not get any error. Any help?

func PollingWorker() {
tiker := time.NewTicker(60 * time.Second)
for _ = range tiker.C {
mu.Lock()
for keyid := range idtime {
d := time.Now().Unix() - idtime[keyid]
if d >= 60 {
// Find nfinstance using keyid
nfinstanceProfile, err := 
config.Conf.FindNFInstanceProfileById(ctx, keyid)
if err != nil {
config.Logrus.Error("Could not find NF Instance Profile 
with ID :" + keyid + " to SUSPEND Status")
}
// change nfStatus of nfinstance to SUSPENDED
err = config.Conf.SuspendNFInstanceNfStatus(ctx, 
nfinstanceProfile, keyid)
if err != nil {
config.Logrus.Error(err)
}
delete(idtime, keyid)
}
}
mu.Unlock()
}
}


BR
Abraham
On Wednesday, November 18, 2020 at 10:51:49 AM UTC+2 Afriyie Abraham 
Kwabena wrote:

> Hi Sulhan,  Anderson,
>
> Thanks for your guidance. It works now using time.Ticker
>
> func worker() {
> tiker := time.NewTicker(30 * time.Second)
> for _ = range tiker.C {
>
> mu.Lock()
> for keyid := range idtime {
>
> d := time.Now().Unix() - idtime[keyid]
> if d >= 60 {
> // delete resouce in database after 60 seconds
> _ = DeleteNFInstance(ctx, keyid)
> }
> }
> mu.Unlock()
> }
> }
>
> BR
> Abraham
>
>
>
> On Tuesday, November 17, 2020 at 9:41:01 PM UTC+2 Shulhan wrote:
>
>>
>>
>> > On 18 Nov 2020, at 01.06, Afriyie Abraham Kwabena  
>> wrote: 
>> > 
>> > Hi, 
>> > 
>> > The UpdateData function is the HTTP handler for the route which matches 
>> the URL and is called after the mux.Router after receiving an incoming 
>> request matches the incoming request 
>> > against the registered route. 
>>
>> ... 
>>
>> > var idtime = make(map[string]int64) 
>> > 
>> > 
>> > func UpdateData(response http.ResponseWriter, request *http.Request) { 
>> > 
>> > var ( 
>> > localVarHTTPMethod = http.MethodPatch 
>> > patchItems model.PatchItem 
>> > ) 
>> > 
>> > id := config.GetIdFromRequest(request) 
>> > 
>> > if request.Method == localVarHTTPMethod { 
>> > 
>> > err := json.NewDecoder(request.Body).Decode(&patchItems) 
>> > if err != nil { 
>> > common.WriteError(response, common.ErrBadRequest) 
>> > return 
>> > } 
>> > 
>> > defer request.Body.Close() 
>> > 
>> > idtime[id] = time.Now().Unix() 
>> > 
>>
>> We still may have data race here. 
>>
>> > 
>> > func worker() { 
>> > mu.Lock() 
>> > for keyid := range idtime { 
>> > 
>> > d := time.Now().Unix() - idtime[keyid] 
>> > if d >= 60 { 
>> > 
>> > // delete resouce in database after 60 seconds 
>> > _ = DeleteNFInstance(ctx, keyid) 
>> > } 
>> > } 
>> > mu.Unlock() 
>> > } 
>> > 
>>
>> ... 
>>
>> > // main function 
>> > func main() { 
>> > r := NewRouter() 
>> > 
>> > go worker() 
>> > 
>> > 
>> > fmt.Println("Start listening") 
>> > fmt.Println(http.ListenAndServe(":8080", r)) 
>> > } 
>> > 
>> > I appreciate your help but am still not able to it work. 
>> > 
>>
>> Looks like your worker only loop once and then it finished. Either you 
>> use time.Sleep() to repeat the loop inside loop or use time.Ticker [1]. 
>>
>> [1] https://pkg.go.dev/time#Ticker 
>>
>>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/9db5a074-0b0a-4f3a-ab20-7c5d67f458a0n%40googlegroups.com.


Re: [go-nuts] How to detect HTTP client stop polling at the server side

2020-11-26 Thread Afriyie Abraham Kwabena
Hi,

Yes from the warning it prints the handler function below and after google 
searching what i did was to mutex.Lock and Unlock the handler function and 
no warning again.
However, my google search people mention of using channels instead of 
mutex. What I would like to ask is, using mutex OK and if not the best way 
of solving it, how can i use
channels in this case.

Handler function below:

func UpdateNFInstance(response http.ResponseWriter, request *http.Request) {

mu.Lock()
defer mu.Unlock()

var (
localVarHTTPMethod = http.MethodPatch
ctx= context.Background()
patchItems model.PatchItem
)

id := config.GetIdFromRequest(request)

if request.Method == localVarHTTPMethod {

if request.Header.Get("Content-Type") != 
"application/json-patch+json" {
common.WriteError(response, 
common.ErrStatusUnsupportedMediaTypePatch)
return
}

err := json.NewDecoder(request.Body).Decode(&patchItems)
if err != nil {
common.WriteError(response, common.ErrBadRequest)
return
}

defer request.Body.Close()

delete(idtime, id) // delete value in map if exit

idtime[id] = time.Now().Unix()

nfProfile, err := config.Conf.FindNFInstanceProfileById(ctx, id)
if err != nil {
common.WriteError(response, common.ErrNotFound)
return
}

if patchItems.Path == "/nfStatus" {

nfProfile.NfStatus = patchItems.Value
nfProfile.LoadTimeStamp = time.Now().String()

success := config.Conf.UpdateNFInstanceHeartBeatNfStatus(ctx, 
nfProfile, id)
if !success {
common.WriteError(response, common.ErrInternalServer)
return
}

if request.URL.Scheme != "" {
scheme = request.URL.Scheme
}
response.Header().Set("Content-Location", 
scheme+"://"+request.Host+request.URL.Path)
response.Header().Set("Response-Desc", "Success")
common.RespondWith3gppJSONPatchJSON(response, 
http.StatusNoContent, nil)

} else {
// patchItems.Path == "/load" information
v, err := strconv.Atoi(patchItems.Value)
if err != nil {
config.Logrus.Errorf("Failed to convert Patch Item Value 
string to integer: %s", err.Error())
}

nfProfile.Load = int32(v)
nfProfile.LoadTimeStamp = time.Now().String()

success := config.Conf.UpdateNFInstanceHeartBeatLoad(ctx, 
nfProfile, id)
if !success {
common.WriteError(response, common.ErrInternalServer)
return
}

if request.URL.Scheme != "" {
scheme = request.URL.Scheme
}
response.Header().Set("Content-Location", 
scheme+"://"+request.Host+request.URL.Path)
response.Header().Set("Response-Desc", "Success")
common.RespondWith3gppJSONPatchJSON(response, 
http.StatusNoContent, nil)

}
} else {
common.WriteError(response, common.ErrMethodNotAllowed)
    return
}
}


BR
Abraham

On Friday, November 27, 2020 at 6:38:52 AM UTC+2 Shulhan wrote:

>
>
> > On 27 Nov 2020, at 07.06, Afriyie Abraham Kwabena  
> wrote:
> > 
> > Hi,
> > 
> > Am experiencing data race warning with my pollingworker function below 
> even though when i build with the -race flag i do not get any error. Any 
> help?
> > 
>
> Usually when you got data race warning it will print the line that cause 
> read and write race condition. Pay attention to both lines and I think you 
> will find the cause.
>
> It's kind of hard to figure it out only through a single function. It 
> could be in config.Conf or in function that manipulate idtime outside the 
> pollingworker.
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/9fae8852-b60d-4c76-9939-b997db3d685cn%40googlegroups.com.


Re: [go-nuts] How to detect HTTP client stop polling at the server side

2020-11-26 Thread Afriyie Abraham Kwabena
()
  
/home/xxx/go/pkg/mod/golang.org/x/net@v0.0.0-20201031054903-ff519b6c9102/http2/server.go:2152
 
+0xc5

Previous read at 0x00cf7a88 by goroutine 18:
  nfnrfapi/services/manag.PollingWorker()
  
/home/xxx/go/src/nfnrfapi/services/manag/api_nf_instance_id_document_Update.go:112
 
+0x1c4

Goroutine 48 (running) created at:
  golang.org/x/net/http2.(*serverConn).processHeaders()
  
/home/xxx/go/pkg/mod/golang.org/x/net@v0.0.0-20201031054903-ff519b6c9102/http2/server.go:1882
 
+0x924
  golang.org/x/net/http2.(*serverConn).processFrame()
  
/home/xxx/go/pkg/mod/golang.org/x/net@v0.0.0-20201031054903-ff519b6c9102/http2/server.go:1410
 
+0x41e
  golang.org/x/net/http2.(*serverConn).processFrameFromReader()
  
/home/xxx/go/pkg/mod/golang.org/x/net@v0.0.0-20201031054903-ff519b6c9102/http2/server.go:1368
 
+0x7d9
  golang.org/x/net/http2.(*serverConn).serve()
  
/home/xxx/go/pkg/mod/golang.org/x/net@v0.0.0-20201031054903-ff519b6c9102/http2/server.go:869
 
+0x14fc
  golang.org/x/net/http2.(*Server).ServeConn()
  
/home/xxx/go/pkg/mod/golang.org/x/net@v0.0.0-20201031054903-ff519b6c9102/http2/server.go:472
 
+0xdc4
  golang.org/x/net/http2.ConfigureServer.func1()
  
/home/xxx/go/pkg/mod/golang.org/x/net@v0.0.0-20201031054903-ff519b6c9102/http2/server.go:298
 
+0x11e
  net/http.(*conn).serve()
  /usr/local/go/src/net/http/server.go:1834 +0x1d5b

Goroutine 18 (running) created at:
  main.main()
  /home/xxx/go/src/nfnrfapi/main.go:41 +0x2c6


On Friday, November 27, 2020 at 8:14:48 AM UTC+2 Afriyie Abraham Kwabena 
wrote:

> Hi,
>
> Yes from the warning it prints the handler function below and after google 
> searching what i did was to mutex.Lock and Unlock the handler function and 
> no warning again.
> However, my google search people mention of using channels instead of 
> mutex. What I would like to ask is, using mutex OK and if not the best way 
> of solving it, how can i use
> channels in this case.
>
> Handler function below:
>
> func UpdateNFInstance(response http.ResponseWriter, request *http.Request) 
> {
>
> mu.Lock()
> defer mu.Unlock()
>
>
> var (
> localVarHTTPMethod = http.MethodPatch
> ctx= context.Background()
>
> patchItems model.PatchItem
> )
>
> id := config.GetIdFromRequest(request)
>
> if request.Method == localVarHTTPMethod {
>
> if request.Header.Get("Content-Type") != 
> "application/json-patch+json" {
> common.WriteError(response, 
> common.ErrStatusUnsupportedMediaTypePatch)
> return
>
> }
>
> err := json.NewDecoder(request.Body).Decode(&patchItems)
> if err != nil {
> common.WriteError(response, common.ErrBadRequest)
> return
> }
>
> defer request.Body.Close()
>
> delete(idtime, id) // delete value in map if exit
>
> idtime[id] = time.Now().Unix()
>
> nfProfile, err := config.Conf.FindNFInstanceProfileById(ctx, id)
> if err != nil {
> common.WriteError(response, common.ErrNotFound)
> return
> }
>
> if patchItems.Path == "/nfStatus" {
>
> nfProfile.NfStatus = patchItems.Value
> nfProfile.LoadTimeStamp = time.Now().String()
>
> success := config.Conf.UpdateNFInstanceHeartBeatNfStatus(ctx, 
> nfProfile, id)
> if !success {
> common.WriteError(response, common.ErrInternalServer)
> return
> }
>
> if request.URL.Scheme != "" {
> scheme = request.URL.Scheme
> }
> response.Header().Set("Content-Location", 
> scheme+"://"+request.Host+request.URL.Path)
> response.Header().Set("Response-Desc", "Success")
> common.RespondWith3gppJSONPatchJSON(response, 
> http.StatusNoContent, nil)
>
> } else {
> // patchItems.Path == "/load" information
> v, err := strconv.Atoi(patchItems.Value)
> if err != nil {
> config.Logrus.Errorf("Failed to convert Patch Item Value 
> string to integer: %s", err.Error())
> }
>
> nfProfile.Load = int32(v)
> nfProfile.LoadTimeStamp = time.Now().String()
>
> success := config.Conf.UpdateNFInstanceHeartBeatLoad(ctx, 
> nfProfile, id)
> if !success {
> common.WriteError(response, common.ErrInternalServer)
> return
> }
>
> if request.URL.Scheme != "" {
> scheme 

Re: [go-nuts] How to detect HTTP client stop polling at the server side

2020-11-27 Thread Afriyie Abraham Kwabena
Hi,

THanks!!

BR
Abraham

On Friday, November 27, 2020 at 11:12:53 AM UTC+2 b.ca...@pobox.com wrote:

> On Friday, 27 November 2020 at 06:14:48 UTC Afriyie Abraham Kwabena wrote:
>
>> What I would like to ask is, using mutex OK and if not the best way of 
>> solving it, how can i use
>> channels in this case.
>>
>
> There's nothing wrong with mutex, but you can use channels for a more 
> native-Go experience.
> This video is well worth watching: 
> https://www.youtube.com/watch?v=5zXAHh5tJqQ
>
> In short, you can get mutex or semaphore-like behaviour by having a 
> channel with fixed depth, and putting/pulling values from it.
> Playground <https://play.golang.org/p/Vg-c8v7N0-6>
>
> mutex := make(chan struct{}, 1)
> ...
>
> mutex <- struct{}{}
> ... do stuff
> <-mutex
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/e59c6a22-030c-479a-ba8a-b61948307b62n%40googlegroups.com.


[go-nuts] How to design HTTP request between HTTP servers

2021-03-20 Thread Afriyie Abraham Kwabena

Hi,

I have been learning Golang for some few months now but still find it 
difficult to design some applications. I have two HTTP servers A and B and 
would like to do the following
1. server A send an HTTP PUT request with JSON body to server B.
2. If server B is not available, server A retry until server B is up and 
respond to the request
3. In server B response body is a timer value received by server A  
4. Server B uses the timer value (eg 45) to send a PATCH request using the 
value as interval. For example in this case, server A send the PATCH 
request to server B every 45 seconds.
5. Server B respond to the PATCH request with either HTTP status code 204 
or status code 404.
6. If status code is 204, that is OK, server A continues to send the PATCH 
request using the 45 seconds interval.
7. If the response status is 404, server A have to start the process again 
from step 1 again to step 6 when 204 status code is received. 

I have tried to write some code which works but restarting from step 1 when 
404 status code is received does not work. Also am not sure if my 
application design is good enough. Any help and comments about my 
application design. Below is my code  

var (
ContentLocation string
Timer  int32
mu  sync.Mutex
)

func SendPUTMessageToServerB() {

msgbytes, err := ioutil.ReadFile("./msg.json")
...

locProfilebytes, err := json.Marshal(pcfprofile)
  ...
 
locVarNRFUrl := "server B url"

profile, resp, err := HandlePUTMessage(locProfilebytes, locVarNRFUrl)

status := resp.StatusCode

if status == http.StatusOK {
logrus.Println("PUT mesage Update SUCCESS")
} else if status == http.StatusCreated {
logrus.Println("PUT message SUCCESS")
} else {

logrus.Println(fmt.Errorf("Wrong status code returned by server B 
%d", status))
}

ContentLocation = resp.Header.Get("Location")
Timer = profile.TimerValue
}

func HandlePUTMessage(filebyte []byte, VarPath string) (Profile, 
*http.Response, error) {

var (
// Set client and set url
localVarHTTPMethod = http.MethodPut
nfp  Profile
)

req, err := http.NewRequest(localVarHTTPMethod, VarPath, 
bytes.NewBuffer(filebyte))
if err != nil {
logrus.Error(err)
}
req.Close = true
req.Header.Set("Content-Type", "application/json")

backoff := 1
for {
res, err := Client.Do(req) 
if err != nil || res == nil {
logrus.Println("Server A Trying to send PUT request ...")
backoff *= 2
if backoff > 20 {
backoff = 20
}
time.Sleep(time.Duration(backoff) * time.Second)
continue
}

defer func() {
if resCloseErr := res.Body.Close(); resCloseErr != nil {
logrus.Errorf("Response body cannot close: %+v", 
resCloseErr)
}
}()

bodybytes, err := ioutil.ReadAll(res.Body)
//localVarHTTPResponse.Body.Close()
if err != nil {
logrus.Error(err)
return nfp, res, err
}

json.Unmarshal(bodybytes, &nfp)
return nfp, res, nil
}
}

// Send PATCH message to server B 
func PATCHMessage() (err error) {
 ...

patchitembytes, err := json.Marshal(patchitem)

...

req, err := http.NewRequest("PATCH", ContentLocation, 
bytes.NewBuffer(patchitembytes))
req.Header.Set("Content-Type", "application/json-patch+json")

response, err := transport.Client.Do(req) // for dev

defer response.Body.Close()

status := response.StatusCode
if status == http.StatusNoContent {

logrus.Info("PATCH message SUCCESS")
} else if status == http.StatusNotFound {

// Here I would like to restart PUT message if status code is 404

logrus.Println("Heart-Beat Message FAILED") 
}
return err
}

// Send a patch message every Timer value
func SendPATCHMessageEveryTimerValue() {

for {
ticker := time.NewTicker(time.Duration(Timer) * time.Second)
mu.Lock()

for _ = range ticker.C {
err := PATCHMessage()
if err != nil {
SendPUTMessage()
}
}
mu.Unlock()
}
}


func main() {

SendPUTMessageToServerB()
go SendPATCHMessageEveryTimerValue()
}



-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/a2481944-2a5c-467b-ba39-6e355fe219aan%40googlegroups.com.