Skip to content
This repository has been archived by the owner on Mar 18, 2022. It is now read-only.

Commit

Permalink
init client base structure
Browse files Browse the repository at this point in the history
Signed-off-by: Marko Kungla <marko.kungla@gmail.com>
  • Loading branch information
mkungla committed Feb 4, 2022
1 parent 32ff024 commit 8b8b252
Show file tree
Hide file tree
Showing 22 changed files with 1,364 additions and 0 deletions.
18 changes: 18 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Editor config helps developers define and maintain consistent
# coding styles between different editors and IDEs
# EditorConfig is awesome: http://editorconfig.org

# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
trim_trailing_whitespace = false
27 changes: 27 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# https://git-scm.com/docs/gitattributes
#
# A gitattributes file is a simple text file that gives attributes to path names
# Each line in gitattributes file is of form: pattern attr1 attr2 ...
# That is, a pattern followed by an attributes list, separated by white spaces.
# When the pattern matches the path in question, the attributes listed on the
# line are given to the path. Each attribute can be in one of these states for a
# given path:

################################################################################
# DEFAULTS
################################################################################
* text=auto
* eol=lf

################################################################################
# TEXT:
# Ensure that the following files, and file name patterns are treated correctly
################################################################################
.editorconfig text
.gitattributes text
.gitignore text
.md text
LICENSE text
*.yml text
*.yaml text

21 changes: 21 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
################################################################################
# GITIGNORE
# repository is place for source code not for binaries if you need to include
# binaries in repository then consider appropriate values .gitattributes
################################################################################

################################################################################
# FILES to ignore
################################################################################
*~
**/*.sw[mnop]
################################################################################
# DIRECTORIES to ignore
################################################################################

################################################################################
# exception rules
################################################################################
!**/*.gitkeep
!**/*go.mod
!**/*README.md
218 changes: 218 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
# options for analysis running
run:
# default concurrency is a available CPU number
# concurrency: 4
# timeout for analysis, e.g. 30s, 5m, default is 1m
timeout: 1m

# exit code when at least one issue was found, default is 1
issues-exit-code: 1

# include test files or not, default is true
tests: true

# list of build tags, all linters use it. Default is empty list.
# build-tags:
# - mytag

# which dirs to skip: issues from them won't be reported;
# can use regexp here: generated.*, regexp is applied on full path;
# default value is empty list, but default dirs are skipped independently
# from this option's value (see skip-dirs-use-default).
# "/" will be replaced by current OS file path separator to properly work
# on Windows.
# skip-dirs:
# - pkg/log

# default is true. Enables skipping of directories:
# vendor$, third_party$, testdata$, examples$, Godeps$, builtin$
skip-dirs-use-default: true

# which files to skip: they will be analyzed, but issues from them
# won't be reported. Default value is empty list, but there is
# no need to include all autogenerated files, we confidently recognize
# autogenerated files. If it's not please let us know.
# "/" will be replaced by current OS file path separator to properly work
# on Windows.
# skip-files:
# - ".*\\.my\\.go$"
# - lib/bad.go

# by default isn't set. If set we pass it to "go list -mod={option}". From "go help modules":
# If invoked with -mod=readonly, the go command is disallowed from the implicit
# automatic updating of go.mod described above. Instead, it fails when any changes
# to go.mod are needed. This setting is most useful to check that go.mod does
# not need updates, such as in a continuous integration and testing system.
# If invoked with -mod=vendor, the go command assumes that the vendor
# directory holds the correct copies of dependencies and ignores
# the dependency descriptions in go.mod.
modules-download-mode: readonly

# Allow multiple parallel golangci-lint instances running.
# If false (default) - golangci-lint acquires file lock on start.
allow-parallel-runners: false

# output configuration options
output:
# colored-line-number|line-number|json|tab|checkstyle|code-climate|junit-xml|github-actions
# default is "colored-line-number"
format: colored-line-number

# print lines of code with issue, default is true
print-issued-lines: true

# print linter name in the end of issue text, default is true
print-linter-name: true

# make issues output unique by line, default is true
uniq-by-line: true

# add a prefix to the output file references; default is no prefix
path-prefix: ""

# sorts results by: filepath, line and column
sort-results: true

issues:
# Independently from option `exclude` we use default exclude patterns,
# it can be disabled by this option. To list all
# excluded by default patterns execute `golangci-lint run --help`.
# Default value for this option is true.
exclude-use-default: true
# Fix found issues (if it's supported by the linter)
fix: false
# Excluding configuration per-path, per-linter, per-text and per-source
exclude-rules:
# Exclude some linters from running on tests files.
- path: _test\.go
linters:
- gocyclo
- errcheck
- dupl
- gosec
# Exclude lll issues for long lines with go:generate
- linters:
- lll
source: "^//go:generate "
- linters:
- lll
source: "^# "
severity:
# Default value is empty string.
# Set the default severity for issues. If severity rules are defined and the issues
# do not match or no severity is provided to the rule this will be the default
# severity applied. Severities should match the supported severity names of the
# selected out format.
# - Code climate: https://docs.codeclimate.com/docs/issues#issue-severity
# - Checkstyle: https://checkstyle.sourceforge.io/property_types.html#severity
# - Github: https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message
# default-severity: error

linters:
disable-all: true
enable:
# Enabled By Default Linters
- deadcode
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- structcheck
- typecheck
- unused
- varcheck
# Disabled By Default Linters
- asciicheck
- bodyclose
- cyclop
- depguard
- dogsled
- dupl
- durationcheck
- errorlint
- exhaustive
- exhaustivestruct
- exportloopref
- forbidigo
- forcetypeassert
- funlen
- gochecknoglobals
- gochecknoinits
- gocognit
- goconst
- gocritic
- gocyclo
- godot
- godox
- goerr113
- gofmt
# - gofumpt
- gci # run it after gofumpt
- goheader
# - goimports
# - gomnd
- gosec
- ifshort
- lll
- makezero
- misspell
- nakedret
- nestif
- nilerr
- nolintlint
- prealloc
- predeclared
- revive
# - nlreturn
- stylecheck
- unconvert
- unparam
- wastedassign
- whitespace

linters-settings:
cyclop:
# the maximal code complexity to report
max-complexity: 15

exhaustivestruct:
# Struct Patterns is list of expressions to match struct packages and names
# The struct packages have the form example.com/package.ExampleStruct
# The matching patterns can use matching syntax from https://pkg.go.dev/path#Match
# If this list is empty, all structs are tested.
struct-patterns:
- "*.Test"
funlen:
lines: 80
statements: 40

gci:
# put imports beginning with prefix after 3rd-party packages;
# only support one prefix
# if not set, use goimports.local-prefixes
local-prefixes: github.com/howijd/
goconst:
ignore-calls: true
ignore-tests: false

goheader:
values:
const:
AUTHOR: The Howijd.Network Authors
template: |-
Copyright {{ YEAR }} {{ AUTHOR }}
SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
http://www.apache.org/licenses/LICENSE-2.0
or LICENSE file in repository root.
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
108 changes: 108 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// Copyright 2022 The Howijd.Network Authors
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
// or LICENSE file in repository root.
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package koios

import (
"context"
"fmt"
"io"
"net/http"
"net/url"
"strings"
"time"
)

// GET sends api http get request to provided relative path with query params
// and returns an HTTP response. When using these methods you are wxpected
// to handle the response according to net/http.Do documentation.
// e.g. Caller should close resp.Body when done reading from it.
func (c *Client) GET(ctx context.Context, path string, query ...url.Values) (*http.Response, error) {
return c.request(ctx, "GET", nil, path, query...)
}

func (c *Client) request(
ctx context.Context,
m string,
body io.Reader,
p string,
query ...url.Values) (*http.Response, error) {
var (
requrl *url.URL
)

p = strings.TrimLeft(p, "/")
c.mux.RLock()
switch len(query) {
case 0:
requrl = c.url.ResolveReference(&url.URL{Path: p})
case 1:
requrl = c.url.ResolveReference(&url.URL{Path: p, RawQuery: query[0].Encode()})
default:
c.mux.RUnlock()
return nil, fmt.Errorf("%w: got %d", ErrURLValuesLenght, len(query))
}
c.mux.RUnlock()

// optain lock to update last ts and total
// request count. Lock will block is another request is already queued.
// e.g. in other go routine.
c.mux.Lock()

// handle rate limit
for !c.lastRequest.IsZero() && time.Since(c.lastRequest) < c.reqInterval {
}

c.lastRequest = time.Now()
c.totalReq++

// Release client so that other requests can use it.
c.mux.Unlock()

req, err := http.NewRequestWithContext(ctx, strings.ToUpper(m), requrl.String(), body)
if err != nil {
return nil, err
}

return c.client.Do(req)
}

func (c *Client) BaseURL() string {
c.mux.RLock()
defer c.mux.RUnlock()
return c.url.String()
}

func (c *Client) TotalRequests() uint {
c.mux.RLock()
defer c.mux.RUnlock()
return c.totalReq
}

func (c *Client) updateBaseURL() error {
c.mux.Lock()
defer c.mux.Unlock()
raw := fmt.Sprintf("%s://%s", c.schema, c.host)
if c.port != 80 && c.port != 443 {
raw = fmt.Sprintf("%s:%d", raw, c.port)
}
raw += "/api/" + c.version + "/"
u, err := url.ParseRequestURI(raw)
if err != nil {
return err
}
c.url = u
return nil
}
Loading

0 comments on commit 8b8b252

Please sign in to comment.