diff options
| -rw-r--r-- | CHANGELOG.adoc | 954 | ||||
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | _doc/CHANGELOG_2024.adoc | 868 | ||||
| -rw-r--r-- | _doc/index.adoc | 3 | ||||
| -rw-r--r-- | pakakeh.go | 7 |
5 files changed, 1044 insertions, 790 deletions
diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index cc9a4256..2c446964 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -1,8 +1,15 @@ +// SPDX-FileCopyrightText: 2025 M. Shulhan <ms@kilabit.info> +// SPDX-License-Identifier: BSD-3-Clause + = pakakeh.go CHANGELOG -:toc: :sectanchors: +:sectlinks: +:toc: -This library is released every month, usually at the first week of month. +This Go module usually released every month, at the first week of the month. + +link:CHANGELOG_2024.html[Changelog in 2024^]. +This is changelog for `pakakeh.go` module since v0.52.0 until v0.58.1. link:CHANGELOG_2023.html[Changelog in 2023^]. This is changelog for `pakakeh.go` module since v0.43.0 until v0.51.0. @@ -20,849 +27,226 @@ link:CHANGELOG_2018-2019.html[Changelog from 2018 to 2019^]. This is changelog for `pakakeh.go` module since v0.1.0 until v0.11.0. -[#v0_58_1] -== pakakeh.go v0.58.1 (2024-12-07) - -[#v0_58_1__enhancements] -=== Enhancements - -lib/play: add custom request to run unsafe directory directly:: -+ --- -As exceptional, the Run and HTTPHandleRun accept the following -request for running program inside custom "go.mod", - ----- -{ - "unsafe_run": <path> -} ----- - -The "unsafe_run" define the path to directory relative to HTTP -server working directory. -Once request accepted it will change the directory into -"unsafe_run" first and then run "go run ." directly. -Go code that executed inside "unsafe_run" should be not -modifiable and safe from mallicious execution. --- - - -lib/play: add option to Run with specific Go version and without race:: -+ -The idea is to allow testing Go code on specific Go version. -For example, before Go 1.22, the for loop with variable is shared -among block statements, which cause every use of that variable is run -with the last value. - - -lib/play: expose the Timeout variable:: -+ -By exposing the Timeout, user can set their maximum time the program -can run in their playground. - - -[#v0_58_0] -== pakakeh.go v0.58.0 (2024-10-06) - -This release update the minimum Go module to 1.22.0, the last version -supported by Go tools. +[#v0_59_0] +== pakakeh.go v0.59.0 (2025-01-06) -[#v0_58_0__breaking_changes] -=== Breaking changes +This is the first release of pakakeh.go on the year 2025. +There are many new features and cleaning up, including packages that +merged into single package with help of type parameters. -lib/http: remove writing StatusNoContent on ResponseTypeNode:: -+ -To make it consistent with RequestTypeNone, the -ResponseTypeNone should not write any response header or -HTTP status code. -It will be handled manually by [Endpoint.Call]. +The first major changes is indicated by using "go 1.23.4" as minimum Go +version in this module, to allow us using new packages like "slices" and +"maps". -[#v0_58_0__new_features] -=== New features +In this release notes, we try new format. +Instead of grouping each changes by Breaking changes, New features, Bug +fixes, Enhancements, and/or Chores; we group them by package. +Each paragraph in the package sections will be prefixed with tag "[BREAKING +CHANGE]", "[NEW FEATURE]", "[BUG FIX]", "[ENHANCEMENT]", "[CHORE]" to +indicates the type of changes. -lib/play: new package for formatting and running Go code:: -+ -Package play provides callable APIs and HTTP handlers to format and -run Go code, similar to Go playground, but using HTTP instead of -WebSocket. -lib/http: add Server method to register handler by function:: -+ --- -The RegisterHandleFunc register a pattern with a handler, similar to -[http.ServeMux.HandleFunc]. -The pattern follow the Go 1.22 format: +[#v0_59_0__lib_binary] +=== lib/binary - [METHOD] PATH +The "lib/binary] is new package that complement the standard binary package. -The METHOD is optional, default to GET. -The PATH must not contains the domain name and space. -Unlike standard library, variable in PATH is read using ":var" not -"{var}". -This endpoint will accept any content type and return the body as is; -it is up to the handler to read and set the content type and the -response headers. +[NEW FEATURE] + +Implement append-only binary that encode the data using [binary.Writer]. +We call them "Apo" for short. -If the METHOD and/or PATH is already registered it will panic. --- +[NEW FEATURE] + +Implement buffer for reading/writing in BigEndian. +The `BigEndianBuffer` provides backing storage for writing (most of) Go +native types into binary in big-endian order. +The zero value of BigEndianBuffer is an empty buffer ready to use. +The following basic types are supported for Write and Read: bool, byte, +int, float, complex, and string. +The slice and array are also supported as long as the slice's element type +is one of basic types. -lib/bytes: add function AppendInt64 and AppendUint64:: -+ -The AppendInt64 append an int64 value into slice of byte. -The AppendUint64 append an uint64 value into slice of byte. +[#v0_59_0__lib_bytes] +=== lib/bytes -[#v0_57_0] -== pakakeh.go v0.57.0 (2024-09-03) +[BREAKING CHANGE] + +In the "lib/bytes" we split the `hexdump` related functions to separate +package, "lib/hexdump". -[#v0_57_0__breaking_changes] -=== Breaking changes -lib/sql: replace [http.FileSystem] with [memfs.MemFS]:: -+ --- -Accepting the [http.FileSystem] means that the parameter can receive an -instance of [embed.FS], but in most cases, it will fail. +[#v0_59_0__lib_floats64] +=== lib/floats64 -Case example, when we embed SQL files for migration under -"db/migration" using the "go:embed" directive, +[BREAKING CHANGE] + +This package has been removed, merged into "slices" package. - //go:embed db/migration/*.sql - var DBMigrationFS embed.FS -and then call the [Migrate] function, it will not find any ".sql" -files inside the "/" directory because the files is stored under -"db/migration/" prefix (also there is no "/" when using embed.FS). --- +[#v0_59_0__lib_hexdump] +=== lib/hexdump -[#v0_57_0__chores] -=== Chores +[NEW FEATURE] + +Package `hexdump` implements reading and writing bytes from and into +hexadecimal number. +It support parsing output from +https://man.archlinux.org/man/hexdump.1[hexdump(1)] tool. -lib/memfs: document the comparison with "go:embed" directive:: -+ --- -Compare it to "go:embed", the memfs package is more flexible and -portable. -Currently, we found three disadvantages of using "go:embed", -- The "go:embed" only works if files or directory to be - embedded is in the same parent directory. -- Accessing the embedded file require the original path. -- No development mode. +[#v0_59_0__lib_http] +=== lib/http -None of those limitation affected the memfs package. --- +[NEW FEATURE] + +In the [lib/http.Client] we add new method `Transport` that return default +HTTP Transport. +The returned [http.Transport] is created after the Client instantiated. +Their value can be customized by user when needed, which should affect +the Transport inside the Client. -[#v0_56_0] -== pakakeh.go v0.56.0 (2024-08-04) +[#v0_59_0__lib_ints] +=== lib/ints -[#v0_56_0__new_features] -=== New features +[BREAKING CHANGE] + +This package has been removed, merged into "slices" package. -cmd/emaildecode: CLI to decode email body to plain text:: -+ -The emaildecode accept file as input. -If the email header contains content-transfer-encoding with value -quoted-printable or base64, it will decode the message body and print it -to stdout as plain text. -[#v0_56_0__bug_fixes] -=== Bug fixes +[#v0_59_0__lib_ints64] +=== lib/ints64 -lib/memfs: another fix for refresh:: -+ -In previous commit we use wrong condition when handling directory "." as -Root. +[BREAKING CHANGE] + +This package has been removed, merged into "slices" package. -[#v0_56_0__enhancements] -=== Enhancements -lib/email: allow message that end lines with LF only:: -+ -Although, a message from network must end with CRLF, a message from -(another) client may have been sanitized and end with LF only. +[#v0_59_0__lib_memfs] +=== lib/memfs -lib/email: decode the message body based on content-transfer-encoding:: -+ -After the header and body has been parsed, if the header contains -Content-Transfer-Encoding, we decode the body into its local formats. -Currently supported encoding is "quoted-printable" and "base64". +[ENHANCEMENT] + +In the "lib/memfs" we refactoring the `Watch` method to use the new +"watchfs/v2" package. -[#v0_56_0__others] -=== Others +[BREAKING CHANGE] + +The old Watcher and DirWatcher types now moved to `watchfs` package. +This changes require exporting method [memfs.MemFS.UpdateContent]. -lib/email: export the Header fields:: -+ -By exporting the fields, this allow the caller to filter or manage the -field manually. -_doc: add partial note and summary for RFC 2183:: -+ -The RFC 2183 is define Content-Disposition header field in the internet -message. +[#v0_59_0__lib_numbers] +=== lib/numbers -lib/ini: mention that marshaling []byte does not supported:: -+ -Due to "byte" is considered as "uint8" during reflection, we cannot tell -whether the value is slice of byte of slice of number with type uint8. +[CHORE] + +In the package level, we remove unused README and LICENSE files. +This package README has been merged into the package documentation and the +LICENSE is same with the module one. +We also remove some package documentation that should be in "lib/slices". -[#v0_55_2] -== pakakeh.go v0.55.2 (2024-07-22) -[#v0_55_2__bug_fix] -=== Bug fix +[#v0_59_0__lib_play] +=== lib/play -lib/memfs: sanitize the Root directory to fix refresh:: -+ -In [MemFS.refresh], if the requested url is "/file1" and [Options.Root] -is ".", the path during refresh become "file1" and if passed to -[filepath.Dir] it will return ".". -This cause the loop on refresh never end because there is no PathNodes -equal with ".". - - -[#v0_55_1] -== pakakeh.go v0.55.1 (2024-06-20) - -[#v0_55_1__enhancements] -=== Enhancements - -lib/http: add request type HTML:: -+ -The RequestTypeHTML define the content type "text/html". - -lib/path: add method Path to Route:: -+ -Unlike String method that may return the key's name in returned path, -the Path method return the path with all the keys has been substituted -with values, even if its empty. - - -[#v0_55_0] -== pakakeh.go v0.55.0 (2024-05-04) - -[#v_55_0__breaking_changes] -=== Breaking changes - -lib/http: refactoring "multipart/form-data" parameters in ClientRequest:: -+ --- -Previously, ClientRequest with type RequestTypeMultipartForm pass the -type "map[string][]byte" in Params. -This type hold the file upload, where key is the file name and []byte is -content of file. -Unfortunately, this model does not correct because a -"multipart/form-data" can contains different field name and file name, -for example +[NEW FEATURE] + +The [lib/play] now has function and HTTP handler to run Go test code. +Since the test must run inside the directory that contains +the Go file to be tested, the [HTTPHandleTest] API accept the following +request format, ---- ---boundary -Content-Disposition: form-data; name="field0"; filename="file0" -Content-Type: application/octet-stream - -<Content of file0> +{ + "goversion": <string>, + "file": <string>, + "body": <string>, + "without_race": <boolean> +} ---- -This changes fix this by changing the parameter type for -RequestTypeMultipartForm to [*multipart.Form], which affect several -functions including [Client.PutFormData] and [GenerateFormData]. --- - -[#v0_55_0__bug_fixes] -=== Bug fixes - -lib/dns: fix packing and unpacking OPT record:: -+ -The RDATA in OPT records can contains zero or _more_ options. -Previously, we only handle unpacking and packing one option, now we -handle multiple options. - -telegram/bot: fix Webhook URL registration:: -+ -Using [path.Join] cause "https://domain" become "https:/domain" which -is not a valid URL. -This bug caused by refactoring in b89afa24f. - - -[#v0_55_0__enhancements] -=== Enhancements - -lib/memfs: set embed file mode to print as octal:: -+ -Using octal in mode make the embedded code more readable, for example mode -with permission "0o644" much more readable than 420". - -telegram/bot: register GET endpoint to test webhook:: -+ --- -The call to get "GET <Webhook.URL.Path>/<Token>" will return HTTP status -200 with JSON body '{"code":200,"message":"OK"}'. - -This endpoint is to check if the bot server is really running. --- - -lib/http: allow all HTTP method to generate HTTP request with body:: -+ -Although the RFC 7231 says that no special defined meaning for a -payload in GET, some implementation of HTTP API sometimes use GET with -content type "application/x-www-form-urlencoded". - -lib/http: add new function [CreateMultipartFileHeader]:: -+ -The CreateMultipartFileHeader help creating [multipart.FileHeader] -from raw bytes, that can be assigned to [*multipart.Form]. - - -[#v0_54_0] -== pakakeh.go v0.54.0 (2024-04-04) - -This is the first release after we move the repository to SourceHut under -different name: "pakakeh.go". -There are several reasons for moving and naming. - -First, related to the name of package. -We accidentally name the package with "share" a common word in English -that does not reflect the content of repository. -By moving to other repository, we can rename it to better and unique -name, in this "pakakeh.go". -Pakakeh is Minang word for tools, and ".go" suffix indicate that the -repository related to Go programming language. - -Second, supporting open source. -The new repository is hosted under sourcehut.org, the founder is known -to support open source, and all their services are licensed under AGPL, -unlike GitHub that are closed sources. - -Third, regarding GitHub CoPilot. -https://docs.github.com/en/site-policy/github-terms/github-terms-of-service#4-license-grant-to-us[The -GitHub Terms of Service], -allow any public content that are hosted there granted them to parse the -content. -On one side, GitHub helps and flourish the open source, but on another -side have an issues -https://githubcopilotinvestigation.com[issues] -regarding scraping the copyleft license. - - -[#v0_54_0__breaking_changes] -=== Breaking changes - -Since we are moving to new repository, we fix all linter warnings and -inconsistencies that we cannot changes on previous module. - -Breaking changes related to naming, - -* api/slack: [Message.IconUrl] become [Message.IconURL] -* lib/dns: DefaultSoaMinumumTtl become DefaultSoaMinimumTTL -* lib/email: [Message.SetBodyHtml] become [Message.SetBodyHTML] -* lib/http: [Client.GenerateHttpRequest] become - [Client.GenerateHTTPRequest] -* lib/http: [ClientOptions.ServerUrl] become [ClientOptions.ServerURL] -* lib/http: [EndpointRequest.HttpWriter] become - [EndpointRequest.HTTPWriter] -* lib/http: [EndpointRequest.HttpRequest] become - [EndpointRequest.HTTPRequest] -* lib/http: [ServerOptions.EnableIndexHtml] become - [ServerOptions.EnableIndexHTML] -* lib/http: [SSEConn.HttpRequest] become [SSEConn.HTTPRequest] -* lib/smtp: [ClientOptions.ServerUrl] become [ClientOptions.ServerURL] -* lib/ssh/sftp: [FileAttrs.SetUid] become [FileAttrs.SetUID] -* lib/ssh/sftp: [FileAttrs.Uid] become [FileAttrs.UID] - -Changes on packages, - -lib/sql: remove deprecated Row type:: -+ -The Row type has been replaced with Meta type with more flexibility -and features for generating type-safe SQL DML. - -lib/memfs: remove deprecated Merge function:: -+ -The Merge function has been replaced with [memfs.MemFS.Merge] for -better API. - -lib: move package "net/html" to "lib/html":: -+ -Putting "html" under "net" package make no sense. -Another reason is to make the package flat under "lib/" directory. - -lib: move package "ssh/config" to "lib/sshconfig":: -+ -Previously the "ssh/config" is used by the parent package "ssh" and -"ssh/sftp" which is break the rule of package layer (the top package -should be imported by sub package, not the other way around). - -lib/http: refactor of RegisterEndpoint and RegisterSSE to non-pointer:: -+ -Once the endpoint registered, the caller should not able to changes -any values on endpoint again. - -lib/http: refactoring NewServer and NewClient:: -+ -The NewServer and NewClient now accept non-pointer options, so the -caller unable to modify the options once the server or client has -been created. - -lib/http: refactor Client methods to use struct ClientRequest:: -+ -Instead of three parameters, the Client methods now accept single struct -[ClientRequest]. - -lib/http: refactoring Client methods to return struct ClientResponse:: -+ -Instead of returning three variables, [http.Response], []byte, and error, -we combine the [http.Response] and []byte into single struct: -ClientResponse. - -lib/http: refactoring type of RequestMethod from int to string:: -+ -The reason is to make storing or encoding the RequestMethod value readable -from user point of view instead of number, 0, 1, 2, etc. - -lib/http: refactor type of RequestType from int to string:: -+ -The reason is to make storing or encoding the RequestType value readable -from human point of view instead of number, 0, 1, 2, etc. - -lib/http: refactoring type of ResponseType from int to string:: -+ -The reason is to make storing or encoding the value readable -from human point of view instead of number, 0, 1, 2, etc. - -lib/http: refactoring FSHandler type to return [*memfs.Node]:: -+ --- -Changing FSHandler type to return [*memfs.Node], allow the handler to -redirect or return custom node. - -One of the use case is when service Single Page Application (SPA), where -route is handled by JavaScript. - -For example, when user requested "/dashboard" but dashboard directory -does not exist, one can write the following handler to return -"/index.html", - - node, _ = memfs.Get(`/index.html`) - return node --- - -lib/dns: refactor [Message.Unpack] to [UnpackMessage]:: -+ --- -The previous API for Message is a little bit weird. -Its provides creating Message manually, but expose the method -[UnpackHeaderQuestion], meanwhile the field packet itself is unexported. - -In order to make it more clear we refactor [Message.Unpack] to -function [UnpackMessage] that accept raw DNS packet. --- - - -[#v0_54_0__new_features] -=== New features - -test/httptest: new helper for testing HTTP server handler:: -+ --- -The Simulate function simulate HTTP server handler by generating -[http.Request] from fields in [SimulateRequest]; and then call -[http.HandlerFunc]. - -The HTTP response from serve along with its raw body and original HTTP -request then returned in [*SimulateResult]. --- - -lib/dns: implements RFC 9460 for SVCB RR and HTTPS RR:: -+ -The dns package now support packing and unpacking DNS with record type 64 -(SVCB) and 65 (HTTPS). - -cmd/ansua: command line interface to help tracking time:: -+ --- -Usage, - - ansua <duration> [ "<command>" ] - -ansua execute a timer on defined duration and optionally run a command -when timer finished. - -When ansua timer is running, one can pause the timer by pressing p+Enter, -and resume it by pressing r+Enter, or stopping it using CTRL+c. --- - - -[#v0_54_0__bug_fixes] -=== Bug fixes - -lib/memfs: trim trailing slash ("/") in the path of Get method:: -+ -The MemFS always store directory without slash. -If caller request a directory node with slash, it will always return nil. - -lib/dns: use ParseUint to parse escaped octet in "\NNN" format:: -+ -Previously, we use ParseInt to parse escaped octet "\NNN", but using -this method only allow decimal from 0 to 127, while the specification -allow 0 to 255. - - -[#v0_54_0__enhancements] -=== Enhancements - -lib/http: handle CORS independently:: -+ --- -Previously, if [CORSOptions.AllowOrigins] not found we return it -immediately without checking request "Access-Control-Request-Method", -"Access-Control-Request-Headers", and other CORS options. - -This changes check each of them, a missing allow origins does not -means empty allowed method, headers, MaxAge, or credentials. --- - -lib/bytes: add parameter networkByteOrder to ParseHexDump:: -+ --- -If networkByteOrder is true, the ParseHexDump read each hex string -in network byte order or as order defined in text. - -While at it, fix reading and parsing single byte hex. --- - -cmd/httpdfs: set default include options to empty:: -+ -By default httpdfs now serve all files under base directory. - - - -[#v0_53_1] -== pakakeh.go v0.53.1 (2024-03-02) - -[#v0_53_1__enhancements] -=== Enhancements - -lib/sql: handle binding with the same name:: -+ -If [Meta.Bind] is called with the same name again, it should replace -the existing named value. - - -lib/dns: ignore invalid message:: -+ --- -If Query return a message but the failed to unpack due to invalid -format, for example - - unpackOPT: data length is out of range - -ignore it instead of disconnect the client connection. --- - - -lib/http: export function to generate "multipart/form-data":: -+ -The GenerateFormData generate the request body with boundary for -HTTP content-type "multipart/form-data" from map[string][]byte. - - -lib/dns: change the log mechanism by mode instead of by level:: -+ --- -This changes introduce three mode of debug: - -* DebugLevelDNS: log error on DNS level, in example empty answer, - ERR_NAME (domain name is invalid or not known) and so on. - -* DebugLevelCache: log cache operations. - -* DebugLevelConnPacket: log low level connection and package, - including request and response. --- - - -[#v0_53_0] -== pakakeh.go v0.53.0 (2024-02-04) - -[#v0_53_0__new_features] -=== New features - -test/mock: implement mock for crypto [rand.Reader]:: -+ --- -The RandReader implement [io.Reader]. -To provide predictable result, the RandReader is seeded with slice of -bytes. -A call to Read will fill the passed bytes with those seed. - -For example, given seed as "abc" (length is three), calling Read with -bytes length five will return "abcab". --- - - -lib/sql: add new type Meta:: -+ --- -Meta contains the DML meta data, including driver name, list of column -names, list of column holders, and list of values. - -The Meta type replace the Row type. --- - - -lib/path: new package to work with path:: -+ --- -The path package provide a new type Route, detached from "lib/http". - -A Route represent a parsed path. -A path can have a key, or binding, that can be replaced with string -value. -For example, "/org/:user/:repo" have two keys "user" and "repo". - -Route handle the path in case-insensitive manner. --- - - -[#v0_53_0__bug_fixes] -=== Bug fixes - -_bin/go-mod-tip: use committer timestamp instead of author timestamp:: -+ -If the tip is rebased to upstream, the author timestamp is not changes, -but the commit timestamp changes. - - -[#v0_53_0__enhancements] -=== Enhancements - -lib/totp: add method GenerateWithTime and GenerateNWithTime:: -+ -The GenerateWithTime and GenerateNWithTime accept parameter -[time.Time] as the relative time for generated password. - - -lib/http: add support for If-Modified-Since in HandleFS:: -+ -If the node modification time is less than requested time value in -request header If-Modified-Since, server will response with -304 Not Modified. - - -lib/http: refactoring Range request, limit content served by server:: -+ --- -When server receive, - - GET /big - Range: bytes=0- - -and the requested resources is quite larger, where writing all content of -file result in i/o timeout, it is best practice [1][2] if the server -write only partial content and let the client continue with the -subsequent Range request. - -In the above case, the server should response with, - - HTTP/1.1 206 Partial content - Content-Range: bytes 0-<limit>/<size> - Content-Length: <limit> - -Where limit is maximum packet that is reasonable [3] for most of the -client. -In this server we choose 8MB as limit. --- - - -lib/http: add method Head to Client:: -+ -The Head method send the HEAD request to path, with optional -headers, and params in query parameters. - - -lib/ini: add method Keys:: -+ -The Keys method return sorted list of all section, subsection, and -variables as string where each of them separated by ":", for example -"section:sub:var". - - -[#v0_52_0] -== pakakeh.go v0.52.0 (2024-01-06) - -[#v0_52_0__new_features] -=== New features - -ssh/config: add method MarshalText and WriteTo:: -+ --- -The MarshalText method encode the Section back to ssh_config format -with two spaces as indentation in key. - -The WriteTo method marshal the Section into text and write it to -[io.Writer] w. --- - -lib/ssh: implement method Output on Client:: -+ --- -The Output method run the command and return its standard output and -error as is. -Any other error beside standard error, like connection, will be returned -as error. --- - -ssh/sftp: implement method MkdirAll on Client:: -+ --- -The MkdirAll create directory on the server, from left to right. -Each directory is separated by '/', where the left part is the parent of -the right part. -This method is similar to [os.MkdirAll]. --- - -cmd/httpdfs: implement [libhttp.Server] with [memfs.MemFS]:: -+ --- -The httpdfs is a program to serve a directory under HTTP. --- - -[#v0_52_0__breaking_changes] -=== Breaking changes - -ssh/config: refactoring the Config merge:: -+ --- -This changes rename method [Config.Prepend] to [Config.Merge]. - -The way that how the other Config merged is changed. -Instead of appending all of other's sections into the current Config, -append the other Config instance to the current instance of Config. - -During [Config.Get] the top Config will be evaluated first, and then the -other Config is evaluated in order of Merge. --- - -ssh/config: add parameter Config to NewSection:: -+ --- -This changes how the Section and parser initialized. - -Previously, the Config depends on the parser to set the workDir and -homeDir and Section depends on Config only on Get; now its the other -way around, from top to bottom. -Config initialized first, then parser initialized using Config instance, -and then Section initialized also using Config instance. --- - -lib/ssh: add parameter context to Execute method:: -+ --- -This changes require the fork of our golang.org/x/crypto. --- +The "file" field define the path to the "_test.go" file, default to +"test_test.go" if its empty. +The "body" field contains the Go code that will be saved to +"file". +The test will run, by default, with "go test -count=1 -race $dirname" +where "$dirname" is the path directory to the "file" relative to where +the program is running. +If "without_race" is true, the test command will not run with "-race" +option. -lib/time: remove UnixMicro and UnixMilli:: -+ --- -Both of those methods has been added into standard library as -[Time.UnixMicro] and [Time.UnixMilli] since Go 1.17. --- +[ENHANCEMENT] + +On package level, the home and cache directory now initialized on package +init since there are never changes when program running. +If Go failed to get the home and cache it will be set to system temporary +directory. -lib/io: removed, this package has been merged into "lib/os":: -+ --- -While some functions are merged to "lib/os", some are not used anymore -like io.Reader. --- +[ENHANCEMENT] + +We also simplify running Go code by removing the field `pid` in the struct +`command` that wait for process ID. +Instead we execute cmd with Run directly. +In the Run function, we use the `UnsafeRun` to store temporary directory +and move the statements that writes `go.mod` and `main.go` into the method +writes of `Request`. +This remove unnecessary `unsafeRun` function. -lib/parser: removed, this package has been merged into lib/strings:: +[#v0_59_0__lib_reflect] +=== lib/reflect -[#v0_52_0__bug_fixes] -=== Bug fixes +[BREAKING CHANGE] + +This release changes the Equal signature from "Equal(v any) bool" to +"Equal(v any) error". +The reason for this changes is to force the method to return an error +message that is understand-able by caller. -ssh/config: fix setting the default values:: -+ --- -The field default value should be set on Get, after all the Host or -Match fields merged. -In this way, if the field key already set, its not overridden by the -default value or subsequent Host or Match value. --- -ssh/config: set the Hostname if its not set on [Config.Get]:: -+ --- -Per manual ssh_config(5) on Hostname, +[#v0_59_0__lib_slices] +=== lib/slices -[quote] -The default is the name given on the command line. +[NEW FEATURE] + +Package "lib/ints", "lib/ints64", and "lib/floats64" are merged into +"slices". +Now that Go has type parameter, we can use it to use the same function +that accept different types for working with slice of int, int64, and +float64. -So, if the requested host name match with one of Host or Match, but -Hostname is not set, it should be default to the requested parameter -name. --- -http/sseclient: fix data race on [Client.Close]:: -+ --- -The data race happened when Close set conn to nil but the consume -method still on Read. -The fix is by waiting for 100ms so consume goroutine can check if closeq -is triggered from Close or not. --- +[#v0_59_0__lib_ssh] +=== lib/ssh -http/sseclient: fix Retry value not set to millisecond:: -+ --- -When client receive "retry:" message, the value is in millisecond, but -when we store it we only convert it to [time.Duration] which default -to nanosecond. +[ENHANCEMENT] + +In the lib/ssh, we implement Run with context internally. +Instead of depends on fork of crypto with CL that needs +https://go-review.googlesource.com/c/crypto/+/552435[proposal^], +we implement them in here so we can update crypto module to the latest +release. -While at it, update comments on field [Client.Retry] and -[Client.Insecure]. --- -ssh/sftp: fix Stat on empty remote file name:: -+ --- -The implementation of SSH server (openssh) for Stat is not consistent with -the RFC. -The RFC mentioned that +[#v0_59_0__lib_watchfs] +=== lib/watchfs -[quote] -An empty path name is valid, and it refers to the user's default -directory (usually the user's home directory). +The `watchfs` package now contains the original, v1, of the +`Watcher` and `DirWatcher` types from "lib/memfs". -But this only working on some command, like Mkdir, but not Stat. --- -ssh/sftp: fix non-nil returned error on Close:: -+ --- -This changes fix the Close that always return an error. --- +[#v0_59_0__lib_watchfs_v2] +=== lib/watchfs/v2 +[NEW FEATURE] + +The "lib/watchfs/v2" is the new package that implement new file and +directory watcher, that replace the Watcher and DirWatcher in the +"lib/memfs". -[#v0_52_0__enhancements] -=== Enhancements +The new implementation, `FileWatcher`, much more simple than what +we have in [memfs.Watcher]. -ssh/config: merge the Section slice values on [Section.merge]:: -+ --- -Instead of using [Section.Set], set the key-value directly. +The new directory watcher, DirWatcher, scan the content of directory in +[fs.DirWatcherOptions.Root] recursively for the files to be watched, using +the [fs.DirWatcherOptions.Includes] field. +A single file, [fs.DirWatcherOptions.FileWatcherOptions.FilePath], will +be watched for changes that trigger re-scanning the content of Root +recursively. -While at it, merge the certificateFile, IdentityFile, knownHostFiles, -and sendEnv. --- +The result of re-scanning is list of the Includes files (only files not +new directory) that are changes, which send to channel C. +On each [os.FileInfo] received from C, a deleted file have +[os.FileInfo.Size] equal to [NodeFlagDeleted]. +The channel send an empty slice if no changes. -ssh/config: set the default UserKnownHostsFile in setDefaults:: -+ --- -While at it, unfold each value of IdentityFile and UserKnownHostsFile -in setDefaults, by expanding "~" into user's home directory or joining -with "config" directory if its relative. --- +The implementation of file changes in this code is naive, using loop and +comparison of mode, modification time, and size; at least it should +works on most operating system. @@ -5,7 +5,7 @@ "pakakeh.go" is a collection of tools, public HTTP APIs, and libraries written and for working with Go programming language. -This library is released every month, usually at the first week of month. +This Go module usually released every month, at the first week of the month. ## Public APIs diff --git a/_doc/CHANGELOG_2024.adoc b/_doc/CHANGELOG_2024.adoc new file mode 100644 index 00000000..cc9a4256 --- /dev/null +++ b/_doc/CHANGELOG_2024.adoc @@ -0,0 +1,868 @@ += pakakeh.go CHANGELOG +:toc: +:sectanchors: + +This library is released every month, usually at the first week of month. + +link:CHANGELOG_2023.html[Changelog in 2023^]. +This is changelog for `pakakeh.go` module since v0.43.0 until v0.51.0. + +link:CHANGELOG_2022.html[Changelog in 2022^]. +This is changelog for `pakakeh.go` module since v0.33.0 until v0.42.0. + +link:CHANGELOG_2021.html[Changelog in 2021^]. +This is changelog for `pakakeh.go` module since v0.22.0 until v0.32.0. + +link:CHANGELOG_2020.html[Changelog in 2020^]. +This is changelog for `pakakeh.go` module since v0.12.0 until v0.21.0. + +link:CHANGELOG_2018-2019.html[Changelog from 2018 to 2019^]. +This is changelog for `pakakeh.go` module since v0.1.0 until v0.11.0. + + +[#v0_58_1] +== pakakeh.go v0.58.1 (2024-12-07) + +[#v0_58_1__enhancements] +=== Enhancements + +lib/play: add custom request to run unsafe directory directly:: ++ +-- +As exceptional, the Run and HTTPHandleRun accept the following +request for running program inside custom "go.mod", + +---- +{ + "unsafe_run": <path> +} +---- + +The "unsafe_run" define the path to directory relative to HTTP +server working directory. +Once request accepted it will change the directory into +"unsafe_run" first and then run "go run ." directly. +Go code that executed inside "unsafe_run" should be not +modifiable and safe from mallicious execution. +-- + + +lib/play: add option to Run with specific Go version and without race:: ++ +The idea is to allow testing Go code on specific Go version. +For example, before Go 1.22, the for loop with variable is shared +among block statements, which cause every use of that variable is run +with the last value. + + +lib/play: expose the Timeout variable:: ++ +By exposing the Timeout, user can set their maximum time the program +can run in their playground. + + +[#v0_58_0] +== pakakeh.go v0.58.0 (2024-10-06) + +This release update the minimum Go module to 1.22.0, the last version +supported by Go tools. + +[#v0_58_0__breaking_changes] +=== Breaking changes + +lib/http: remove writing StatusNoContent on ResponseTypeNode:: ++ +To make it consistent with RequestTypeNone, the +ResponseTypeNone should not write any response header or +HTTP status code. +It will be handled manually by [Endpoint.Call]. + +[#v0_58_0__new_features] +=== New features + +lib/play: new package for formatting and running Go code:: ++ +Package play provides callable APIs and HTTP handlers to format and +run Go code, similar to Go playground, but using HTTP instead of +WebSocket. + +lib/http: add Server method to register handler by function:: ++ +-- +The RegisterHandleFunc register a pattern with a handler, similar to +[http.ServeMux.HandleFunc]. +The pattern follow the Go 1.22 format: + + [METHOD] PATH + +The METHOD is optional, default to GET. +The PATH must not contains the domain name and space. +Unlike standard library, variable in PATH is read using ":var" not +"{var}". +This endpoint will accept any content type and return the body as is; +it is up to the handler to read and set the content type and the +response headers. + +If the METHOD and/or PATH is already registered it will panic. +-- + + +lib/bytes: add function AppendInt64 and AppendUint64:: ++ +The AppendInt64 append an int64 value into slice of byte. +The AppendUint64 append an uint64 value into slice of byte. + + +[#v0_57_0] +== pakakeh.go v0.57.0 (2024-09-03) + +[#v0_57_0__breaking_changes] +=== Breaking changes + +lib/sql: replace [http.FileSystem] with [memfs.MemFS]:: ++ +-- +Accepting the [http.FileSystem] means that the parameter can receive an +instance of [embed.FS], but in most cases, it will fail. + +Case example, when we embed SQL files for migration under +"db/migration" using the "go:embed" directive, + + //go:embed db/migration/*.sql + var DBMigrationFS embed.FS + +and then call the [Migrate] function, it will not find any ".sql" +files inside the "/" directory because the files is stored under +"db/migration/" prefix (also there is no "/" when using embed.FS). +-- + +[#v0_57_0__chores] +=== Chores + +lib/memfs: document the comparison with "go:embed" directive:: ++ +-- +Compare it to "go:embed", the memfs package is more flexible and +portable. +Currently, we found three disadvantages of using "go:embed", + +- The "go:embed" only works if files or directory to be + embedded is in the same parent directory. +- Accessing the embedded file require the original path. +- No development mode. + +None of those limitation affected the memfs package. +-- + + +[#v0_56_0] +== pakakeh.go v0.56.0 (2024-08-04) + +[#v0_56_0__new_features] +=== New features + +cmd/emaildecode: CLI to decode email body to plain text:: ++ +The emaildecode accept file as input. +If the email header contains content-transfer-encoding with value +quoted-printable or base64, it will decode the message body and print it +to stdout as plain text. + +[#v0_56_0__bug_fixes] +=== Bug fixes + +lib/memfs: another fix for refresh:: ++ +In previous commit we use wrong condition when handling directory "." as +Root. + +[#v0_56_0__enhancements] +=== Enhancements + +lib/email: allow message that end lines with LF only:: ++ +Although, a message from network must end with CRLF, a message from +(another) client may have been sanitized and end with LF only. + +lib/email: decode the message body based on content-transfer-encoding:: ++ +After the header and body has been parsed, if the header contains +Content-Transfer-Encoding, we decode the body into its local formats. +Currently supported encoding is "quoted-printable" and "base64". + +[#v0_56_0__others] +=== Others + +lib/email: export the Header fields:: ++ +By exporting the fields, this allow the caller to filter or manage the +field manually. + +_doc: add partial note and summary for RFC 2183:: ++ +The RFC 2183 is define Content-Disposition header field in the internet +message. + +lib/ini: mention that marshaling []byte does not supported:: ++ +Due to "byte" is considered as "uint8" during reflection, we cannot tell +whether the value is slice of byte of slice of number with type uint8. + + +[#v0_55_2] +== pakakeh.go v0.55.2 (2024-07-22) + +[#v0_55_2__bug_fix] +=== Bug fix + +lib/memfs: sanitize the Root directory to fix refresh:: ++ +In [MemFS.refresh], if the requested url is "/file1" and [Options.Root] +is ".", the path during refresh become "file1" and if passed to +[filepath.Dir] it will return ".". +This cause the loop on refresh never end because there is no PathNodes +equal with ".". + + +[#v0_55_1] +== pakakeh.go v0.55.1 (2024-06-20) + +[#v0_55_1__enhancements] +=== Enhancements + +lib/http: add request type HTML:: ++ +The RequestTypeHTML define the content type "text/html". + +lib/path: add method Path to Route:: ++ +Unlike String method that may return the key's name in returned path, +the Path method return the path with all the keys has been substituted +with values, even if its empty. + + +[#v0_55_0] +== pakakeh.go v0.55.0 (2024-05-04) + +[#v_55_0__breaking_changes] +=== Breaking changes + +lib/http: refactoring "multipart/form-data" parameters in ClientRequest:: ++ +-- +Previously, ClientRequest with type RequestTypeMultipartForm pass the +type "map[string][]byte" in Params. +This type hold the file upload, where key is the file name and []byte is +content of file. +Unfortunately, this model does not correct because a +"multipart/form-data" can contains different field name and file name, +for example + +---- +--boundary +Content-Disposition: form-data; name="field0"; filename="file0" +Content-Type: application/octet-stream + +<Content of file0> +---- + +This changes fix this by changing the parameter type for +RequestTypeMultipartForm to [*multipart.Form], which affect several +functions including [Client.PutFormData] and [GenerateFormData]. +-- + +[#v0_55_0__bug_fixes] +=== Bug fixes + +lib/dns: fix packing and unpacking OPT record:: ++ +The RDATA in OPT records can contains zero or _more_ options. +Previously, we only handle unpacking and packing one option, now we +handle multiple options. + +telegram/bot: fix Webhook URL registration:: ++ +Using [path.Join] cause "https://domain" become "https:/domain" which +is not a valid URL. +This bug caused by refactoring in b89afa24f. + + +[#v0_55_0__enhancements] +=== Enhancements + +lib/memfs: set embed file mode to print as octal:: ++ +Using octal in mode make the embedded code more readable, for example mode +with permission "0o644" much more readable than 420". + +telegram/bot: register GET endpoint to test webhook:: ++ +-- +The call to get "GET <Webhook.URL.Path>/<Token>" will return HTTP status +200 with JSON body '{"code":200,"message":"OK"}'. + +This endpoint is to check if the bot server is really running. +-- + +lib/http: allow all HTTP method to generate HTTP request with body:: ++ +Although the RFC 7231 says that no special defined meaning for a +payload in GET, some implementation of HTTP API sometimes use GET with +content type "application/x-www-form-urlencoded". + +lib/http: add new function [CreateMultipartFileHeader]:: ++ +The CreateMultipartFileHeader help creating [multipart.FileHeader] +from raw bytes, that can be assigned to [*multipart.Form]. + + +[#v0_54_0] +== pakakeh.go v0.54.0 (2024-04-04) + +This is the first release after we move the repository to SourceHut under +different name: "pakakeh.go". +There are several reasons for moving and naming. + +First, related to the name of package. +We accidentally name the package with "share" a common word in English +that does not reflect the content of repository. +By moving to other repository, we can rename it to better and unique +name, in this "pakakeh.go". +Pakakeh is Minang word for tools, and ".go" suffix indicate that the +repository related to Go programming language. + +Second, supporting open source. +The new repository is hosted under sourcehut.org, the founder is known +to support open source, and all their services are licensed under AGPL, +unlike GitHub that are closed sources. + +Third, regarding GitHub CoPilot. +https://docs.github.com/en/site-policy/github-terms/github-terms-of-service#4-license-grant-to-us[The +GitHub Terms of Service], +allow any public content that are hosted there granted them to parse the +content. +On one side, GitHub helps and flourish the open source, but on another +side have an issues +https://githubcopilotinvestigation.com[issues] +regarding scraping the copyleft license. + + +[#v0_54_0__breaking_changes] +=== Breaking changes + +Since we are moving to new repository, we fix all linter warnings and +inconsistencies that we cannot changes on previous module. + +Breaking changes related to naming, + +* api/slack: [Message.IconUrl] become [Message.IconURL] +* lib/dns: DefaultSoaMinumumTtl become DefaultSoaMinimumTTL +* lib/email: [Message.SetBodyHtml] become [Message.SetBodyHTML] +* lib/http: [Client.GenerateHttpRequest] become + [Client.GenerateHTTPRequest] +* lib/http: [ClientOptions.ServerUrl] become [ClientOptions.ServerURL] +* lib/http: [EndpointRequest.HttpWriter] become + [EndpointRequest.HTTPWriter] +* lib/http: [EndpointRequest.HttpRequest] become + [EndpointRequest.HTTPRequest] +* lib/http: [ServerOptions.EnableIndexHtml] become + [ServerOptions.EnableIndexHTML] +* lib/http: [SSEConn.HttpRequest] become [SSEConn.HTTPRequest] +* lib/smtp: [ClientOptions.ServerUrl] become [ClientOptions.ServerURL] +* lib/ssh/sftp: [FileAttrs.SetUid] become [FileAttrs.SetUID] +* lib/ssh/sftp: [FileAttrs.Uid] become [FileAttrs.UID] + +Changes on packages, + +lib/sql: remove deprecated Row type:: ++ +The Row type has been replaced with Meta type with more flexibility +and features for generating type-safe SQL DML. + +lib/memfs: remove deprecated Merge function:: ++ +The Merge function has been replaced with [memfs.MemFS.Merge] for +better API. + +lib: move package "net/html" to "lib/html":: ++ +Putting "html" under "net" package make no sense. +Another reason is to make the package flat under "lib/" directory. + +lib: move package "ssh/config" to "lib/sshconfig":: ++ +Previously the "ssh/config" is used by the parent package "ssh" and +"ssh/sftp" which is break the rule of package layer (the top package +should be imported by sub package, not the other way around). + +lib/http: refactor of RegisterEndpoint and RegisterSSE to non-pointer:: ++ +Once the endpoint registered, the caller should not able to changes +any values on endpoint again. + +lib/http: refactoring NewServer and NewClient:: ++ +The NewServer and NewClient now accept non-pointer options, so the +caller unable to modify the options once the server or client has +been created. + +lib/http: refactor Client methods to use struct ClientRequest:: ++ +Instead of three parameters, the Client methods now accept single struct +[ClientRequest]. + +lib/http: refactoring Client methods to return struct ClientResponse:: ++ +Instead of returning three variables, [http.Response], []byte, and error, +we combine the [http.Response] and []byte into single struct: +ClientResponse. + +lib/http: refactoring type of RequestMethod from int to string:: ++ +The reason is to make storing or encoding the RequestMethod value readable +from user point of view instead of number, 0, 1, 2, etc. + +lib/http: refactor type of RequestType from int to string:: ++ +The reason is to make storing or encoding the RequestType value readable +from human point of view instead of number, 0, 1, 2, etc. + +lib/http: refactoring type of ResponseType from int to string:: ++ +The reason is to make storing or encoding the value readable +from human point of view instead of number, 0, 1, 2, etc. + +lib/http: refactoring FSHandler type to return [*memfs.Node]:: ++ +-- +Changing FSHandler type to return [*memfs.Node], allow the handler to +redirect or return custom node. + +One of the use case is when service Single Page Application (SPA), where +route is handled by JavaScript. + +For example, when user requested "/dashboard" but dashboard directory +does not exist, one can write the following handler to return +"/index.html", + + node, _ = memfs.Get(`/index.html`) + return node +-- + +lib/dns: refactor [Message.Unpack] to [UnpackMessage]:: ++ +-- +The previous API for Message is a little bit weird. +Its provides creating Message manually, but expose the method +[UnpackHeaderQuestion], meanwhile the field packet itself is unexported. + +In order to make it more clear we refactor [Message.Unpack] to +function [UnpackMessage] that accept raw DNS packet. +-- + + +[#v0_54_0__new_features] +=== New features + +test/httptest: new helper for testing HTTP server handler:: ++ +-- +The Simulate function simulate HTTP server handler by generating +[http.Request] from fields in [SimulateRequest]; and then call +[http.HandlerFunc]. + +The HTTP response from serve along with its raw body and original HTTP +request then returned in [*SimulateResult]. +-- + +lib/dns: implements RFC 9460 for SVCB RR and HTTPS RR:: ++ +The dns package now support packing and unpacking DNS with record type 64 +(SVCB) and 65 (HTTPS). + +cmd/ansua: command line interface to help tracking time:: ++ +-- +Usage, + + ansua <duration> [ "<command>" ] + +ansua execute a timer on defined duration and optionally run a command +when timer finished. + +When ansua timer is running, one can pause the timer by pressing p+Enter, +and resume it by pressing r+Enter, or stopping it using CTRL+c. +-- + + +[#v0_54_0__bug_fixes] +=== Bug fixes + +lib/memfs: trim trailing slash ("/") in the path of Get method:: ++ +The MemFS always store directory without slash. +If caller request a directory node with slash, it will always return nil. + +lib/dns: use ParseUint to parse escaped octet in "\NNN" format:: ++ +Previously, we use ParseInt to parse escaped octet "\NNN", but using +this method only allow decimal from 0 to 127, while the specification +allow 0 to 255. + + +[#v0_54_0__enhancements] +=== Enhancements + +lib/http: handle CORS independently:: ++ +-- +Previously, if [CORSOptions.AllowOrigins] not found we return it +immediately without checking request "Access-Control-Request-Method", +"Access-Control-Request-Headers", and other CORS options. + +This changes check each of them, a missing allow origins does not +means empty allowed method, headers, MaxAge, or credentials. +-- + +lib/bytes: add parameter networkByteOrder to ParseHexDump:: ++ +-- +If networkByteOrder is true, the ParseHexDump read each hex string +in network byte order or as order defined in text. + +While at it, fix reading and parsing single byte hex. +-- + +cmd/httpdfs: set default include options to empty:: ++ +By default httpdfs now serve all files under base directory. + + + +[#v0_53_1] +== pakakeh.go v0.53.1 (2024-03-02) + +[#v0_53_1__enhancements] +=== Enhancements + +lib/sql: handle binding with the same name:: ++ +If [Meta.Bind] is called with the same name again, it should replace +the existing named value. + + +lib/dns: ignore invalid message:: ++ +-- +If Query return a message but the failed to unpack due to invalid +format, for example + + unpackOPT: data length is out of range + +ignore it instead of disconnect the client connection. +-- + + +lib/http: export function to generate "multipart/form-data":: ++ +The GenerateFormData generate the request body with boundary for +HTTP content-type "multipart/form-data" from map[string][]byte. + + +lib/dns: change the log mechanism by mode instead of by level:: ++ +-- +This changes introduce three mode of debug: + +* DebugLevelDNS: log error on DNS level, in example empty answer, + ERR_NAME (domain name is invalid or not known) and so on. + +* DebugLevelCache: log cache operations. + +* DebugLevelConnPacket: log low level connection and package, + including request and response. +-- + + +[#v0_53_0] +== pakakeh.go v0.53.0 (2024-02-04) + +[#v0_53_0__new_features] +=== New features + +test/mock: implement mock for crypto [rand.Reader]:: ++ +-- +The RandReader implement [io.Reader]. +To provide predictable result, the RandReader is seeded with slice of +bytes. +A call to Read will fill the passed bytes with those seed. + +For example, given seed as "abc" (length is three), calling Read with +bytes length five will return "abcab". +-- + + +lib/sql: add new type Meta:: ++ +-- +Meta contains the DML meta data, including driver name, list of column +names, list of column holders, and list of values. + +The Meta type replace the Row type. +-- + + +lib/path: new package to work with path:: ++ +-- +The path package provide a new type Route, detached from "lib/http". + +A Route represent a parsed path. +A path can have a key, or binding, that can be replaced with string +value. +For example, "/org/:user/:repo" have two keys "user" and "repo". + +Route handle the path in case-insensitive manner. +-- + + +[#v0_53_0__bug_fixes] +=== Bug fixes + +_bin/go-mod-tip: use committer timestamp instead of author timestamp:: ++ +If the tip is rebased to upstream, the author timestamp is not changes, +but the commit timestamp changes. + + +[#v0_53_0__enhancements] +=== Enhancements + +lib/totp: add method GenerateWithTime and GenerateNWithTime:: ++ +The GenerateWithTime and GenerateNWithTime accept parameter +[time.Time] as the relative time for generated password. + + +lib/http: add support for If-Modified-Since in HandleFS:: ++ +If the node modification time is less than requested time value in +request header If-Modified-Since, server will response with +304 Not Modified. + + +lib/http: refactoring Range request, limit content served by server:: ++ +-- +When server receive, + + GET /big + Range: bytes=0- + +and the requested resources is quite larger, where writing all content of +file result in i/o timeout, it is best practice [1][2] if the server +write only partial content and let the client continue with the +subsequent Range request. + +In the above case, the server should response with, + + HTTP/1.1 206 Partial content + Content-Range: bytes 0-<limit>/<size> + Content-Length: <limit> + +Where limit is maximum packet that is reasonable [3] for most of the +client. +In this server we choose 8MB as limit. +-- + + +lib/http: add method Head to Client:: ++ +The Head method send the HEAD request to path, with optional +headers, and params in query parameters. + + +lib/ini: add method Keys:: ++ +The Keys method return sorted list of all section, subsection, and +variables as string where each of them separated by ":", for example +"section:sub:var". + + +[#v0_52_0] +== pakakeh.go v0.52.0 (2024-01-06) + +[#v0_52_0__new_features] +=== New features + +ssh/config: add method MarshalText and WriteTo:: ++ +-- +The MarshalText method encode the Section back to ssh_config format +with two spaces as indentation in key. + +The WriteTo method marshal the Section into text and write it to +[io.Writer] w. +-- + +lib/ssh: implement method Output on Client:: ++ +-- +The Output method run the command and return its standard output and +error as is. +Any other error beside standard error, like connection, will be returned +as error. +-- + +ssh/sftp: implement method MkdirAll on Client:: ++ +-- +The MkdirAll create directory on the server, from left to right. +Each directory is separated by '/', where the left part is the parent of +the right part. +This method is similar to [os.MkdirAll]. +-- + +cmd/httpdfs: implement [libhttp.Server] with [memfs.MemFS]:: ++ +-- +The httpdfs is a program to serve a directory under HTTP. +-- + +[#v0_52_0__breaking_changes] +=== Breaking changes + +ssh/config: refactoring the Config merge:: ++ +-- +This changes rename method [Config.Prepend] to [Config.Merge]. + +The way that how the other Config merged is changed. +Instead of appending all of other's sections into the current Config, +append the other Config instance to the current instance of Config. + +During [Config.Get] the top Config will be evaluated first, and then the +other Config is evaluated in order of Merge. +-- + +ssh/config: add parameter Config to NewSection:: ++ +-- +This changes how the Section and parser initialized. + +Previously, the Config depends on the parser to set the workDir and +homeDir and Section depends on Config only on Get; now its the other +way around, from top to bottom. +Config initialized first, then parser initialized using Config instance, +and then Section initialized also using Config instance. +-- + +lib/ssh: add parameter context to Execute method:: ++ +-- +This changes require the fork of our golang.org/x/crypto. +-- + +lib/time: remove UnixMicro and UnixMilli:: ++ +-- +Both of those methods has been added into standard library as +[Time.UnixMicro] and [Time.UnixMilli] since Go 1.17. +-- + +lib/io: removed, this package has been merged into "lib/os":: ++ +-- +While some functions are merged to "lib/os", some are not used anymore +like io.Reader. +-- + +lib/parser: removed, this package has been merged into lib/strings:: + + +[#v0_52_0__bug_fixes] +=== Bug fixes + +ssh/config: fix setting the default values:: ++ +-- +The field default value should be set on Get, after all the Host or +Match fields merged. +In this way, if the field key already set, its not overridden by the +default value or subsequent Host or Match value. +-- + +ssh/config: set the Hostname if its not set on [Config.Get]:: ++ +-- +Per manual ssh_config(5) on Hostname, + +[quote] +The default is the name given on the command line. + +So, if the requested host name match with one of Host or Match, but +Hostname is not set, it should be default to the requested parameter +name. +-- + +http/sseclient: fix data race on [Client.Close]:: ++ +-- +The data race happened when Close set conn to nil but the consume +method still on Read. +The fix is by waiting for 100ms so consume goroutine can check if closeq +is triggered from Close or not. +-- + +http/sseclient: fix Retry value not set to millisecond:: ++ +-- +When client receive "retry:" message, the value is in millisecond, but +when we store it we only convert it to [time.Duration] which default +to nanosecond. + +While at it, update comments on field [Client.Retry] and +[Client.Insecure]. +-- + +ssh/sftp: fix Stat on empty remote file name:: ++ +-- +The implementation of SSH server (openssh) for Stat is not consistent with +the RFC. +The RFC mentioned that + +[quote] +An empty path name is valid, and it refers to the user's default +directory (usually the user's home directory). + +But this only working on some command, like Mkdir, but not Stat. +-- + +ssh/sftp: fix non-nil returned error on Close:: ++ +-- +This changes fix the Close that always return an error. +-- + + +[#v0_52_0__enhancements] +=== Enhancements + +ssh/config: merge the Section slice values on [Section.merge]:: ++ +-- +Instead of using [Section.Set], set the key-value directly. + +While at it, merge the certificateFile, IdentityFile, knownHostFiles, +and sendEnv. +-- + +ssh/config: set the default UserKnownHostsFile in setDefaults:: ++ +-- +While at it, unfold each value of IdentityFile and UserKnownHostsFile +in setDefaults, by expanding "~" into user's home directory or joining +with "config" directory if its relative. +-- diff --git a/_doc/index.adoc b/_doc/index.adoc index 5f71f567..b6802b9e 100644 --- a/_doc/index.adoc +++ b/_doc/index.adoc @@ -41,6 +41,9 @@ This library is released every month, usually at the first week of month. link:CHANGELOG.html[Latest changelog^]. +link:CHANGELOG_2024.html[Changelog in 2023^]. +Changelog for `pakakeh.go` module since v0.42.0 until v0.58.1. + link:CHANGELOG_2023.html[Changelog in 2023^]. Changelog for `pakakeh.go` module since v0.43.0 until v0.51.0. @@ -1,6 +1,5 @@ -// Copyright 2018, Shulhan <ms@kilabit.info>. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. +// SPDX-FileCopyrightText: 2018 M. Shulhan <ms@kilabit.info> +// SPDX-License-Identifier: BSD-3-Clause // Package pakakeh contains public APIs and libraries for working with Go // language, and tools written in Go. @@ -8,5 +7,5 @@ package pakakeh var ( // Version of this module. - Version = `0.58.1` + Version = `0.59.0` ) |
